<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="Hexo Theme Redefine">
    
    <meta name="author" content="雲之残骸">
    <!-- preconnect -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    
    
    <!--- Seo Part-->
    
    <link rel="canonical" href="https://wreckloud.github.io/2023/09/17/cpp-基础/"/>
    <meta name="robots" content="index,follow">
    <meta name="googlebot" content="index,follow">
    <meta name="revisit-after" content="1 days">
    
        <meta name="description" content="是关于C++基础的笔记,由我朋友 @EMCC 所编写.">
<meta property="og:type" content="article">
<meta property="og:title" content="C++基础">
<meta property="og:url" content="https://wreckloud.github.io/2023/09/17/CPP-%E5%9F%BA%E7%A1%80/index.html">
<meta property="og:site_name" content="赛博狼窝">
<meta property="og:description" content="是关于C++基础的笔记,由我朋友 @EMCC 所编写.">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gd-hbimg.huaban.com/8c1c874271d1e5c3649251f076bb2978aeefc8ce42c2-ZHcmVA">
<meta property="og:image" content="https://gd-hbimg.huaban.com/d02191ef7703f72efc7df591fb8587d700e2862ea867-pVoRZp">
<meta property="og:image" content="https://gd-hbimg.huaban.com/b6b4b891d33f1aa861bdd6ad528a5544c6622faca1d5-NTIgD6_fw1200webp">
<meta property="article:published_time" content="2023-09-17T10:31:41.000Z">
<meta property="article:modified_time" content="2023-09-17T14:57:04.018Z">
<meta property="article:author" content="Wreckloud">
<meta property="article:tag" content="学习笔记">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gd-hbimg.huaban.com/8c1c874271d1e5c3649251f076bb2978aeefc8ce42c2-ZHcmVA">
    
    
    <!--- Icon Part-->
    <link rel="icon" type="image/png" href="/images/web.png" sizes="192x192">
    <link rel="apple-touch-icon" sizes="180x180" href="/images/web.png">
    <meta name="theme-color" content="#A31F34">
    <link rel="shortcut icon" href="/images/web.png">
    <!--- Page Info-->
    
    <title>
        
            C++基础 -
        
        赛博狼窝
    </title>
    
<link rel="stylesheet" href="/css/style.css">


    
        
<link rel="stylesheet" href="/css/build/styles.css">

    

    
<link rel="stylesheet" href="/fonts/fonts.css">

    
<link rel="stylesheet" href="/fonts/Satoshi/satoshi.css">

    
<link rel="stylesheet" href="/fonts/Chillax/chillax.css">

    <!--- Font Part-->
    
    
        <link href="" rel="stylesheet">
    
    
    

    <!--- Inject Part-->
    
    <script id="hexo-configurations">
    let Global = window.Global || {};
    Global.hexo_config = {"hostname":"wreckloud.github.io","root":"/","language":"zh-CN","path":"search.xml"};
    Global.theme_config = {"articles":{"style":{"font_size":"16px","line_height":1.5,"image_border_radius":"4px","image_alignment":"center","image_caption":true,"link_icon":true},"word_count":{"enable":true,"count":true,"min2read":true},"author_label":{"enable":true,"auto":false,"list":[]},"code_block":{"copy":false,"style":"simple","font":{"enable":"ture","family":null,"url":null}},"toc":{"enable":true,"max_depth":3,"number":false,"expand":true,"init_open":true},"copyright":false,"lazyload":true,"recommendation":{"enable":false,"title":"推荐阅读","limit":3,"mobile_limit":2,"placeholder":"/images/wallhaven-wqery6-light.webp","skip_dirs":[]}},"colors":{"primary":"#A31F34","secondary":null},"global":{"fonts":{"chinese":{"enable":false,"family":null,"url":null},"english":{"enable":false,"family":null,"url":null}},"content_max_width":"1000px","sidebar_width":"210px","hover":{"shadow":true,"scale":false},"scroll_progress":{"bar":false,"percentage":true},"website_counter":{"url":"https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js","enable":false,"site_pv":true,"site_uv":true,"post_pv":true},"single_page":true,"open_graph":true,"google_analytics":{"enable":false,"id":null}},"home_banner":{"enable":true,"style":"fixed","image":{"light":"/images/wallhaven-wqery6-light.webp","dark":"/images/wallhaven-wqery6-dark.webp"},"title":"今天也要好心情!","subtitle":{"text":["正在加载..."],"hitokoto":{"enable":"ture","api":"https://v1.hitokoto.cn"},"typing_speed":130,"backing_speed":80,"starting_delay":1500,"backing_delay":3000,"loop":false,"smart_backspace":true},"text_color":{"light":"#fff","dark":"#d1d1b6"},"text_style":{"title_size":"2.8rem","subtitle_size":"1.5rem","line_height":1.2},"custom_font":{"enable":false,"family":null,"url":null},"social_links":{"enable":false,"links":{"github":null,"instagram":null,"zhihu":null,"twitter":null,"bilibili":null},"qrs":{"weixin":null}}},"plugins":{"feed":{"enable":false},"aplayer":{"enable":false,"type":"fixed","audios":[{"name":null,"artist":null,"url":null,"cover":null}]},"mermaid":{"enable":true,"version":"9.3.0"}},"version":"2.4.4","navbar":{"auto_hide":false,"color":{"left":"#f78736","right":"#367df7","transparency":35},"links":{"Home":{"path":"/","icon":"fa-solid fa-house"},"tags":{"path":"/tag/","icon":"fa-solid fa-tags"},"Status":{"path":"/masonry/","icon":"fa-solid fa-sparkles"},"About":{"icon":"fa-solid fa-feather","submenus":{"关于我":"/about/","我的b站":"https://space.bilibili.com/177822535?spm_id_from=333.1007.0.0"}}},"search":{"enable":true,"preload":true}},"page_templates":{"friends_column":2,"tags_style":"blur"},"home":{"sidebar":{"enable":true,"position":"left","first_item":"info","announcement":"欢迎朋友们参观!  不过刚刚搭好现在还没什么内容呢...","links":null},"article_date_format":"auto","categories":{"enable":true,"limit":3},"tags":{"enable":true,"limit":3}},"footerStart":"2023/9/17 14:00:00"};
    Global.language_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 个月前","year":"%s 年前"};
    Global.data_config = {"masonry":true};
  </script>
    
    <!--- Fontawesome Part-->
    
<link rel="stylesheet" href="/fontawesome/fontawesome.min.css">

    
<link rel="stylesheet" href="/fontawesome/brands.min.css">

    
<link rel="stylesheet" href="/fontawesome/solid.min.css">

    
<link rel="stylesheet" href="/fontawesome/regular.min.css">

    
    
    
    
<meta name="generator" content="Hexo 6.3.0"></head>


<body>
<div class="progress-bar-container">
    

    
        <span class="pjax-progress-bar"></span>
        <span class="swup-progress-icon">
            <i class="fa-solid fa-circle-notch fa-spin"></i>
        </span>
    
</div>


<main class="page-container" id="swup">

    

    <div class="main-content-container">


        <div class="main-content-header">
            <header class="navbar-container">
    
    <div class="navbar-content">
        <div class="left">
            
            <a class="logo-title" href="https://wreckloud.github.io/">
                
                赛博狼窝
                
            </a>
        </div>

        <div class="right">
            <!-- PC -->
            <div class="desktop">
                <ul class="navbar-list">
                    
                        
                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class="" 
                                    href="/"  >
                                    
                                        
                                            <i class="fa-solid fa-house"></i>
                                        
                                        首页
                                    
                                </a>
                                <!-- Submenu -->
                                
                            </li>
                    
                        
                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class="" 
                                    href="/tag/"  >
                                    
                                        
                                            <i class="fa-solid fa-tags"></i>
                                        
                                        标签
                                    
                                </a>
                                <!-- Submenu -->
                                
                            </li>
                    
                        
                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class="" 
                                    href="/masonry/"  >
                                    
                                        
                                            <i class="fa-solid fa-sparkles"></i>
                                        
                                        画廊
                                    
                                </a>
                                <!-- Submenu -->
                                
                            </li>
                    
                        
                            <li class="navbar-item">
                                <!-- Menu -->
                                <a class="has-dropdown" 
                                    href="#" onClick="return false;">
                                    
                                        
                                            <i class="fa-solid fa-feather"></i>
                                        
                                        关于&nbsp;<i class="fa-solid fa-chevron-down"></i>
                                    
                                </a>
                                <!-- Submenu -->
                                
                                    <ul class="sub-menu">
                                    
                                        <li>
                                        <a href="/about/">关于我
                                        </a>
                                        </li>
                                    
                                        <li>
                                        <a target="_blank" rel="noopener" href="https://space.bilibili.com/177822535?spm_id_from=333.1007.0.0">我的B站
                                        </a>
                                        </li>
                                    
                                    </ul>
                                
                            </li>
                    
                    
                        <li class="navbar-item search search-popup-trigger">
                            <i class="fa-solid fa-magnifying-glass"></i>
                        </li>
                    
                </ul>
            </div>
            <!-- Mobile -->
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fa-solid fa-magnifying-glass"></i></div>
                
                <div class="icon-item navbar-bar">
                    <div class="navbar-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- Mobile drawer -->
    <div class="navbar-drawer w-full absolute top-0 left-0 bg-background-color">
        <ul class="drawer-navbar-list flex flex-col justify-start items-center">
            
                
                    <li class="drawer-navbar-item text-base my-1.5 flex justify-center items-center">
                        <a class="rounded-3xl py-1.5 px-5 hover:border hover:!text-primary active:!text-primary group " 
                        href="/"  >
                             
                                
                                    <i class="fa-solid fa-house"></i>
                                
                                首页
                            
                        </a>
                    </li>
                    <!-- Submenu -->
                    
            
                
                    <li class="drawer-navbar-item text-base my-1.5 flex justify-center items-center">
                        <a class="rounded-3xl py-1.5 px-5 hover:border hover:!text-primary active:!text-primary group " 
                        href="/tag/"  >
                             
                                
                                    <i class="fa-solid fa-tags"></i>
                                
                                标签
                            
                        </a>
                    </li>
                    <!-- Submenu -->
                    
            
                
                    <li class="drawer-navbar-item text-base my-1.5 flex justify-center items-center">
                        <a class="rounded-3xl py-1.5 px-5 hover:border hover:!text-primary active:!text-primary group " 
                        href="/masonry/"  >
                             
                                
                                    <i class="fa-solid fa-sparkles"></i>
                                
                                画廊
                            
                        </a>
                    </li>
                    <!-- Submenu -->
                    
            
                
                    <li class="drawer-navbar-item text-base my-1.5 flex justify-center items-center">
                        <a class="rounded-3xl py-1.5 px-5 hover:border hover:!text-primary active:!text-primary group has-dropdown" 
                        href="#" onClick="return false;">
                            
                                
                                    <i class="fa-solid fa-feather"></i>
                                
                                关于&nbsp;<i class="group-hover:rotate-180 transition-transform fa-solid fa-chevron-down"></i>
                            
                        </a>
                    </li>
                    <!-- Submenu -->
                              
                        
                            <li class="text-base flex justify-center items-center hover:underline active:underline hover:underline-offset-1 rounded-3xl">
                                <a class="py-0.5" href="/about/">关于我</a>
                            </li>
                        
                            <li class="text-base flex justify-center items-center hover:underline active:underline hover:underline-offset-1 rounded-3xl">
                                <a class="py-0.5" target="_blank" rel="noopener" href="https://space.bilibili.com/177822535?spm_id_from=333.1007.0.0">我的B站</a>
                            </li>
                        
                    
            

        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="main-content-body">

            

            <div class="main-content">

                
                    <div class="post-page-container">
    <div class="article-content-container">

        <div class="article-title">
            
                
                
                <img src="/../img/C++%E5%B0%81%E9%9D%A2.jpg" alt="C++基础" class="max-w-none"/>
                
                <h1 class="article-title-cover">C++基础</h1>
            
            </div>
            
                    
        
        
            <div class="article-header">
                <div class="avatar">
                    <img src="/images/default.png">
                </div>
                <div class="info">
                    <div class="author">
                        <span class="name">雲之残骸</span>
                        
                            <span class="author-label">Lv1</span>
                        
                    </div>
                    <div class="meta-info">
                        <div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fa-regular fa-pen-fancy"></i>&nbsp;
        <span class="desktop">2023-09-17 18:31:41</span>
        <span class="mobile">2023-09-17 18:31:41</span>
        <span class="hover-info">创建</span>
    </span>
    
        <span class="article-date article-meta-item">
            <i class="fa-regular fa-wrench"></i>&nbsp;
            <span class="desktop">2023-09-17 22:57:04</span>
            <span class="mobile">2023-09-17 22:57:04</span>
            <span class="hover-info">更新</span>
        </span>
    

    
    
        <span class="article-tags article-meta-item">
            <i class="fa-regular fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">学习笔记</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
        <span class="article-wordcount article-meta-item">
            <i class="fa-regular fa-typewriter"></i>&nbsp;<span>52.2k 字</span>
        </span>
    
    
        <span class="article-min2read article-meta-item">
            <i class="fa-regular fa-clock"></i>&nbsp;<span>207 分钟</span>
        </span>
    
    
</div>

                    </div>
                </div>
            </div>
        

        


        <div class="article-content markdown-body">
            <p>很用心的笔记.由我朋友@EMCC所编写,他的b站:<br><a class="link"   target="_blank" rel="noopener" href="https://space.bilibili.com/1843315943" >EMC方的b站空间 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//基础语法</span></span><br><span class="line"><span class="comment">//函数高级</span></span><br><span class="line"><span class="comment">//面向对象</span></span><br><span class="line"><span class="comment">//继承和多态 </span></span><br><span class="line"><span class="comment">//文件操作</span></span><br><span class="line"><span class="comment">//左值右值</span></span><br><span class="line"><span class="comment">//C++类型转换</span></span><br><span class="line"><span class="comment">//预处理</span></span><br><span class="line"><span class="comment">//异常处理</span></span><br><span class="line"><span class="comment">//常用数据结构和常用算法</span></span><br><span class="line"><span class="comment">//模板基础</span></span><br><span class="line"><span class="comment">//STL基础、使用</span></span><br><span class="line">常用标准库</span><br><span class="line">正则表达式、正则库</span><br><span class="line">socket网络编程基础</span><br><span class="line">C++<span class="number">11</span>、<span class="number">14</span>、<span class="number">17</span>、<span class="number">20</span>、<span class="number">23</span>等新特性</span><br><span class="line">    萃取、模板泛型编程进阶、元编程、函数式编程</span><br><span class="line">    并发、多线程和多进程、线程库</span><br><span class="line">    <span class="comment">//智能指针</span></span><br><span class="line">    <span class="comment">//Lambda表达式</span></span><br><span class="line">	<span class="comment">//强类型枚举</span></span><br><span class="line">    <span class="comment">//可变参数模板</span></span><br><span class="line">    等....</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">后续方向：</span><br><span class="line">QT</span><br><span class="line">QML+Quick</span><br><span class="line">MFC</span><br><span class="line">音、视频开发</span><br><span class="line">图像处理</span><br><span class="line">游戏引擎（游戏开发）</span><br><span class="line">信号处理（通信）</span><br><span class="line">服务器开发</span><br><span class="line">嵌入式开发</span><br><span class="line">等等</span><br><span class="line">    </span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<p>[TOC]</p>
<h1 id="引用（左值引用）"><a href="#引用（左值引用）" class="headerlink" title="引用（左值引用）"></a>引用（左值引用）</h1><h2 id="基本概念和语法"><a href="#基本概念和语法" class="headerlink" title="基本概念和语法"></a>基本概念和语法</h2><hr>
<p>&#x3D;&#x3D;本章所有内容都是针对C++98标准的左值引用。&#x3D;&#x3D;</p>
<p><a class="link"   target="_blank" rel="noopener" href="https://www.runoob.com/cplusplus/cpp-references.html" >C++中的引用是一种特殊的变量，它是另一个已存在变量的别名，可以通过引用或原始变量来访问同一块内存空间。 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<p>引用的语法是在变量类型后加上<code>&amp;</code>符号，然后给引用一个初始值</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>; <span class="comment">// 声明一个普通变量a</span></span><br><span class="line"><span class="type">int</span> &amp;b = a; <span class="comment">// 声明一个引用b，它是a的别名</span></span><br><span class="line"></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;a =&quot;</span> &lt;&lt; a &lt;&lt;endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;b = &quot;</span> &lt;&lt; b &lt;&lt;endl;</span><br><span class="line">b = <span class="number">100</span>; <span class="comment">// a和b是同一块内存区域的两个名称，对b进行操作等价于对a进行操作</span></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;a = &quot;</span> &lt;&lt; a &lt;&lt;endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;b = &quot;</span> &lt;&lt; b &lt;&lt;endl;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出结果：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">10</span></span><br><span class="line">b = <span class="number">10</span></span><br><span class="line">a = <span class="number">100</span></span><br><span class="line">b = <span class="number">100</span></span><br></pre></td></tr></table></figure></div>

<p><strong>引用的作用有以下几点：</strong></p>
<ul>
<li>可以简化指针的操作，避免使用<code>*</code>和<code>&amp;</code>符号来取值或取地址。</li>
<li>可以提高函数参数传递的效率，避免复制大量数据。</li>
<li>可以使函数返回多个值，而不仅仅是一个。</li>
<li>可以实现运算符重载等高级功能。</li>
</ul>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><hr>
<p><strong>引用的注意事项有以下几点：</strong></p>
<ul>
<li><p>引用&#x3D;&#x3D;必须&#x3D;&#x3D;在声明时&#x3D;&#x3D;初始化&#x3D;&#x3D;，不能像指针那样先声明后赋值。</p>
</li>
<li><p>引用一旦初始化，就&#x3D;&#x3D;不能改变指向&#x3D;&#x3D;其他变量，否则会修改原始变量的值。</p>
</li>
<li><p>引用&#x3D;&#x3D;不能指向空值&#x3D;&#x3D;或&#x3D;&#x3D;无效地址&#x3D;&#x3D;，否则会导致程序崩溃。</p>
</li>
<li><p>引用&#x3D;&#x3D;不占用额外的内存空间&#x3D;&#x3D;，它只是原始变量的另一个名称。</p>
</li>
<li><p>一个变量可以有多个引用，也就是说，可以定义多个引用指向同一个变量。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>; </span><br><span class="line"><span class="type">int</span> &amp;r1 = a; <span class="comment">// r1是a的引用 </span></span><br><span class="line"><span class="type">int</span> &amp;r2 = a; <span class="comment">// r2也是a的引用 </span></span><br><span class="line">cout &lt;&lt; r1 &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; r2 &lt;&lt; endl; <span class="comment">// 输出10 10</span></span><br></pre></td></tr></table></figure></div>
</li>
<li><p>引用不能有引用，也就是说，不能定义一个引用指向另一个引用。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>; </span><br><span class="line"><span class="type">int</span> &amp;r1 = a; <span class="comment">// r1是a的引用 </span></span><br><span class="line"><span class="type">int</span> &amp;r2 = r1; <span class="comment">// 错误，不能定义一个引用指向另一个引用</span></span><br></pre></td></tr></table></figure></div>

<p>但是，可以定义一个变量和一个引用同时指向另一个引用。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>; </span><br><span class="line"><span class="type">int</span> &amp;r1 = a; <span class="comment">// r1是a的引用 </span></span><br><span class="line"><span class="type">int</span> *p = &amp;r1; <span class="comment">// p是指向r1的指针 </span></span><br><span class="line"><span class="type">int</span> &amp;r2 = *p; <span class="comment">// r2是p所指对象的引用，也就是r1的别名 </span></span><br><span class="line">cout &lt;&lt; *p &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; r2 &lt;&lt; endl; <span class="comment">// 输出10 10</span></span><br></pre></td></tr></table></figure></div></li>
</ul>
<h2 id="引用做函数参数"><a href="#引用做函数参数" class="headerlink" title="引用做函数参数"></a>引用做函数参数</h2><hr>
<p>当引用作为函数参数时，需要注意以下几点：</p>
<ul>
<li>如果参数只需要读取而不修改，可以使用常量引用来提高效率和安全性。</li>
<li>如果参数需要修改，并且希望修改能够反映到实参上，可以使用普通引用来传递。</li>
<li>如果参数是类对象或结构体等复杂类型，并且需要修改其内容或调用其成员函数，可以使用普通引用来传递。</li>
</ul>
<p>引用的本质是一个常指针（指针常量），在编译器内部实现为指向原始变量地址的常量。引用传递相当于指针传递。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 值传递</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap1</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span> temp = a; </span><br><span class="line">    a = b; </span><br><span class="line">    b = temp; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 指针传递 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap2</span><span class="params">(<span class="type">int</span> *a, <span class="type">int</span> *b)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span> temp = *a; </span><br><span class="line">    *a = *b; </span><br><span class="line">    *b = temp; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 引用传递 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap3</span><span class="params">(<span class="type">int</span> &amp;a, <span class="type">int</span> &amp;b)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span> temp = a; </span><br><span class="line">    a = b; </span><br><span class="line">    b = temp; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">	<span class="type">int</span> x = <span class="number">10</span>, y = <span class="number">20</span>;</span><br><span class="line"></span><br><span class="line">	<span class="built_in">swap1</span>(x, y); <span class="comment">// x和y不会交换 </span></span><br><span class="line">	<span class="built_in">swap2</span>(&amp;x, &amp;y); <span class="comment">// x和y会交换 </span></span><br><span class="line">	<span class="built_in">swap3</span>(x, y); <span class="comment">// x和y会交换，a是x的别名，b是y的别名</span></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="引用做函数返回值"><a href="#引用做函数返回值" class="headerlink" title="引用做函数返回值"></a>引用做函数返回值</h2><hr>
<p><strong>当引用作为函数返回值时，需要注意以下几点：</strong></p>
<ul>
<li>不要返回局部变量的引用，因为局部变量在函数结束后会被销毁，导致返回无效地址。</li>
<li>&#x3D;&#x3D;不建议&#x3D;&#x3D;返回堆区对象的引用。</li>
<li>可以返回静态局部变量或全局变量的引用，因为这些变量在程序结束前都有效。</li>
<li>可以返回类对象或结构体等复杂类型的成员变量或成员函数的引用。</li>
</ul>
<p><strong>返回堆区对象的引用是不安全的，有以下几种可能的风险：</strong></p>
<ul>
<li>如果在函数内部释放了堆区对象的内存，那么返回的引用就是一个空指针，指向一个无效的地址。</li>
<li>如果在函数外部释放了堆区对象的内存，那么可能会导致重复释放或者内存泄漏，因为函数外部不一定知道引用指向的是堆区对象。</li>
<li>如果在函数外部修改了堆区对象的值，那么可能会影响到其他地方使用该对象的逻辑，因为堆区对象是共享的。</li>
</ul>
<p>一般来说，不建议返回堆区对象的引用。如果需要返回动态分配的内存，可以使用智能指针或者容器类来管理内存。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 返回局部变量的引用 </span></span><br><span class="line"><span class="function"><span class="type">int</span>&amp; <span class="title">func1</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span> a = <span class="number">10</span>; <span class="comment">// 局部变量 </span></span><br><span class="line">    <span class="keyword">return</span> a; <span class="comment">// 错误！ </span></span><br><span class="line">&#125; <span class="comment">// 局部变量在函数结束后会被销毁，导致返回无效地址</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 返回堆区对象的引用 </span></span><br><span class="line"><span class="function"><span class="type">int</span>&amp; <span class="title">func2</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span>* p = <span class="keyword">new</span> <span class="built_in">int</span>(<span class="number">20</span>);</span><br><span class="line">    <span class="keyword">return</span> p;</span><br><span class="line">&#125; <span class="comment">// 不建议</span></span><br></pre></td></tr></table></figure></div>

<p>引用做函数返回值时，如果返回的是一个静态变量，那么这个引用就可以作为左值，也就是可以被赋值或修改。这是因为静态变量在函数结束后不会被销毁，它的生命周期和作用域都延长了，所以返回的引用仍然有效。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 返回一个静态变量的引用 </span></span><br><span class="line"><span class="function"><span class="type">int</span>&amp; <span class="title">func</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">static</span> <span class="type">int</span> x = <span class="number">10</span>; <span class="comment">// 静态变量 </span></span><br><span class="line">    <span class="keyword">return</span> x; <span class="comment">// 返回引用 </span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span>&amp; a = <span class="built_in">func</span>(); <span class="comment">// 接收返回的引用 </span></span><br><span class="line">    cout &lt;&lt; a &lt;&lt; endl; <span class="comment">// 输出10 </span></span><br><span class="line">    a = <span class="number">20</span>; <span class="comment">// 修改引用指向的值 </span></span><br><span class="line">    cout &lt;&lt; <span class="built_in">func</span>() &lt;&lt; endl; <span class="comment">// 输出20</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="引用的本质"><a href="#引用的本质" class="headerlink" title="引用的本质"></a>引用的本质</h2><hr>
<p>这一节根据黑马程序员的C++教程（详细在B站搜索”C++“，播放量最高的就是）编写，也许并不正确，请读者自行甄辨。</p>
<p>引用的本质是一种被限制的指针，它在内部实现时是一个指针常量，也就是说，它指向的对象不能改变，但对象的值可以改变。</p>
<p><strong>引用和指针有以下区别：</strong></p>
<ul>
<li>引用必须在定义时初始化，并且不能重新赋值，而指针可以在任何时候初始化和赋值。</li>
<li>引用不占用额外的内存空间，而指针占用一个存储地址的空间。</li>
<li>引用使用起来更加简洁和安全，不需要解引用操作符<code>*</code>，也不会出现空指针或野指针的问题。</li>
<li>引用只能有一级，不能有多级引用，而指针可以有多级。</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义一个变量a和一个引用r </span></span><br><span class="line"><span class="type">int</span> a = <span class="number">10</span>; </span><br><span class="line"><span class="type">int</span> &amp;r = a; <span class="comment">// 相当于 int *const r = &amp;a; //常量指针的指向不可以修改，值可以修改</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过r修改a的值 </span></span><br><span class="line">r = <span class="number">20</span>; </span><br><span class="line">cout &lt;&lt; a &lt;&lt; endl; <span class="comment">// 输出20</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个函数swap，使用引用作为参数 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap</span><span class="params">(<span class="type">int</span> &amp;x, <span class="type">int</span> &amp;y)</span> </span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    <span class="type">int</span> temp = x; </span><br><span class="line">    x = y; </span><br><span class="line">    y = temp; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用swap函数 </span></span><br><span class="line"><span class="type">int</span> m = <span class="number">10</span>, n = <span class="number">20</span>; </span><br><span class="line"><span class="built_in">swap</span>(m, n); </span><br><span class="line">cout &lt;&lt; m &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; n &lt;&lt; endl; <span class="comment">// 输出20 10</span></span><br></pre></td></tr></table></figure></div>

<h2 id="常量引用"><a href="#常量引用" class="headerlink" title="常量引用"></a>常量引用</h2><hr>
<p>常量引用是对<code>const</code>的引用，也就是说，它把它所指向的对象看作是常量，因此不可以通过该引用来修改它所指向的对象的值。</p>
<p><strong>常量引用的作用有以下几点：</strong></p>
<ul>
<li>可以避免不必要的拷贝，提高效率。</li>
<li>可以保护被引用的对象，防止意外修改。</li>
<li>可以接受字面值或表达式作为初始值，而普通引用不行。</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> &amp;a = <span class="number">42</span>; <span class="comment">// 错误：普通引用必须绑定到一个对象上，而不能绑定到一个字面值或表达式</span></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> &amp;r = <span class="number">42</span>;<span class="comment">// 正确：const引用可以绑定到字面值或表达式上，const引用可以让编译器为字面值或表达式创建一个临时变量，并将引用绑定到该临时变量上</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个普通变量i和一个常量变量ci </span></span><br><span class="line"><span class="type">int</span> i = <span class="number">10</span>; </span><br><span class="line"><span class="type">const</span> <span class="type">int</span> ci = <span class="number">20</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个常量引用ri，绑定到i </span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> &amp;ri = i;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个常量引用rci，绑定到ci </span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> &amp;rci = ci;</span><br><span class="line"></span><br><span class="line">rci = <span class="number">30</span>; <span class="comment">// 错误：不能通过常量引用修改被引用的对象 </span></span><br><span class="line">ri = <span class="number">40</span>; <span class="comment">// 错误：不能通过常量引用修改被引用的对象</span></span><br><span class="line"></span><br><span class="line">i = <span class="number">50</span>; <span class="comment">// 正确：可以直接修改普通变量 </span></span><br><span class="line">cout &lt;&lt; ri &lt;&lt; endl; <span class="comment">// 输出50</span></span><br><span class="line"></span><br><span class="line">cout &lt;&lt; r + ri &lt;&lt; endl; <span class="comment">// 输出92</span></span><br></pre></td></tr></table></figure></div>

<h1 id="函数-高级篇"><a href="#函数-高级篇" class="headerlink" title="函数_高级篇"></a>函数_高级篇</h1><h2 id="函数重载"><a href="#函数重载" class="headerlink" title="函数重载"></a>函数重载</h2><hr>
<h3 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h3><hr>
<p>函数重载是指在同一作用域内，可以有多个同名函数，只要它们的参数个数、类型或参数顺序不同即可。这样，当调用这个函数时，编译器会根据传入的实参自动选择合适的函数进行调用。</p>
<p>下面的示例是三个重载的函数。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">double</span> <span class="title">add</span><span class="params">(<span class="type">int</span> a, <span class="type">double</span> b)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">double</span> <span class="title">add</span><span class="params">(<span class="type">double</span> b, <span class="type">int</span> a)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h3 id="注意事项-1"><a href="#注意事项-1" class="headerlink" title="注意事项"></a>注意事项</h3><hr>
<ul>
<li><p>函数重载必须在同一作用域内。</p>
</li>
<li><p>函数重载的函数名必须相同，但函数的参数列表必须不同。</p>
</li>
<li><p>函数重载不能只是函数参数名的不同。</p>
</li>
<li><p>参数列表的不同可以包括参数的类型、个数或顺序。</p>
</li>
<li><p>重载的函数可以有不同的返回值类型，即函数的返回值不作为函数重载的条件</p>
</li>
<li><p>不能仅仅通过为普通变量添加或删除<code>const</code>修饰符来重载一个函数</p>
</li>
<li><p>可以对函数的常量性进行重载，即可以同时定义一个常量函数和一个非常量函数。</p>
</li>
<li><p>可以对类成员函数进行重载。（有关类将在之后的内容中提到）</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;foo(int x): &quot;</span> &lt;&lt; x &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> <span class="comment">// 错误：函数的返回值不作为函数重载的条件</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span> x)</span> <span class="comment">// 错误：不能仅通过为普通变量参数添加const修饰符来重载函数</span></span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;foo(const int x): &quot;</span> &lt;&lt; x &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">code<span class="comment">// 重载函数示例1：参数个数不同</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">sum</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">sum</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b, <span class="type">int</span> c)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b + c;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 重载函数示例2：参数类型不同</span></span><br><span class="line"><span class="function"><span class="type">double</span> <span class="title">sum</span><span class="params">(<span class="type">double</span> a, <span class="type">double</span> b)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">sum</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 重载函数示例3：常量性重载</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;non-const foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> <span class="type">const</span> </span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;const foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 重载类成员函数</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass2</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;non-const foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> <span class="type">const</span> </span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;const foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">// 调用重载函数示例1</span></span><br><span class="line">  <span class="type">int</span> x = <span class="built_in">sum</span>(<span class="number">1</span>, <span class="number">2</span>);</span><br><span class="line">  <span class="type">int</span> y = <span class="built_in">sum</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 调用重载函数示例2</span></span><br><span class="line">  <span class="type">double</span> a = <span class="built_in">sum</span>(<span class="number">1.0</span>, <span class="number">2.0</span>);</span><br><span class="line">  <span class="type">int</span> b = <span class="built_in">sum</span>(<span class="number">1</span>, <span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 调用重载函数示例3</span></span><br><span class="line">  MyClass obj1;</span><br><span class="line">  <span class="type">const</span> MyClass obj2;</span><br><span class="line">  obj1.<span class="built_in">foo</span>(); <span class="comment">// 调用非常量函数</span></span><br><span class="line">  obj2.<span class="built_in">foo</span>(); <span class="comment">// 调用常量函数</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 调用重载类成员函数</span></span><br><span class="line">  MyClass2 obj3;</span><br><span class="line">  <span class="type">const</span> MyClass2 obj4;</span><br><span class="line">  obj3.<span class="built_in">foo</span>(); <span class="comment">// 调用非常量函数</span></span><br><span class="line">  obj4.<span class="built_in">foo</span>(); <span class="comment">// 调用常量函数</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>引用作为函数参数时，可以使用引用的类型和常量性来进行函数重载。</p>
<p>使用引用作为函数参数进行函数重载的<strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span>&amp; x)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 处理一个非常量引用</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span>&amp; x)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 处理一个常量引用</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>当有多个函数重载时，&#x3D;&#x3D;如果某个函数的参数既可以被传递为引用，也可以被传递为值，那么编译器会优先选择传值调用&#x3D;&#x3D;</p>
<p>因为传递值可以避免引用的问题，并且可以更好地利用编译器的优化。如果需要显式地调用一个特定的函数重载，可以使用类型转换或显式地声明参数类型来调用该函数。</p>
<p><strong>例如：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 处理一个整数</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span>&amp; x)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 处理一个常量引用</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>如果我们调用 <code>foo(42)</code>，那么编译器会选择第一个函数，因为它可以直接将整数值 42 传递给函数参数 <code>x</code>，而不需要创建一个临时的引用对象。这样可以更快地执行，因为传递值比传递引用更高效。</p>
<p>但是，如果我们调用 <code>foo(i)</code>，其中 <code>i</code> 是一个整数变量，则编译器会选择第二个函数，因为它可以使用一个引用来访问 <code>i</code>，并且这个引用可以被声明为常量引用，从而保证 <code>i</code> 的值不会被修改。</p>
<p>如果我们需要显式地调用一个特定的函数重载，可以使用类型转换或显式地声明参数类型来调用该函数。</p>
<p>例如，我们可以使用以下方式来调用第一个函数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">foo</span>(<span class="built_in">static_cast</span>&lt;<span class="type">const</span> <span class="type">int</span>&amp;&gt;(<span class="number">42</span>));</span><br></pre></td></tr></table></figure></div>

<p>或者我们可以使用以下方式来调用第二个函数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">42</span>;</span><br><span class="line"><span class="built_in">foo</span>(<span class="built_in">static_cast</span>&lt;<span class="type">int</span>&gt;(i));</span><br></pre></td></tr></table></figure></div>

<p>在这两个例子中，我们使用 <code>static_cast</code> 强制将值类型转换为引用类型或将引用类型转换为值类型。这样可以显式地指定需要调用的函数版本。</p>
</li>
<li><p>两个使用引用作为参数的重载函数<strong>示例</strong>：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span>&amp; x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;   </span><br><span class="line">    <span class="comment">// 处理一个非常量引用 </span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span>&amp; x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;  </span><br><span class="line">    <span class="comment">// 处理一个常量引用</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p>对于这两个重载函数，当传入一个字面常量时，编译器会选择调用 <code>foo(const int&amp; x)</code>，例如：<code>foo(10)</code>，因为字面数值是常量，不能被修改，因此需要传递一个常量引用。</p>
<p>如果传入一个变量，例如： <code>int i = 10; foo(i);</code>，则会选择调用 <code>foo(int&amp; x)</code>，因为该函数接受一个非常量引用，可以修改传入的参数。</p>
<p>如果传入的参数是一个 <code>const</code> 类型的变量，则编译器会选择调用 <code>foo(const int&amp; x)</code>。</p>
</li>
<li><p>不建议在重载函数时使用默认参数，这会非常容易出错，这里不做过多解释</p>
</li>
</ul>
<h2 id="函数的默认参数"><a href="#函数的默认参数" class="headerlink" title="函数的默认参数"></a>函数的默认参数</h2><hr>
<p>函数的默认参数是指在函数定义或声明时，为形参指定一个默认值，这样在调用函数时，如果没有给这个形参赋值（没有对应的实参），那么就使用这个默认值。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//带默认参数的函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n, <span class="type">float</span> b = <span class="number">1.2</span>, <span class="type">char</span> c = <span class="string">&#x27;@&#x27;</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; c &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">func</span>(<span class="number">10</span>); <span class="comment">//相当于func(10, 1.2, &#x27;@&#x27;)</span></span><br><span class="line">	<span class="built_in">func</span>(<span class="number">20</span>, <span class="number">9.8</span>); <span class="comment">//相当于func(20, 9.8, &#x27;@&#x27;)</span></span><br><span class="line">	<span class="built_in">func</span>(<span class="number">30</span>, <span class="number">5.5</span>, <span class="string">&#x27;#&#x27;</span>); <span class="comment">//不使用任何默认值</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出结果：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10</span>, <span class="number">1.2</span>, @</span><br><span class="line"><span class="number">20</span>, <span class="number">9.8</span>, @</span><br><span class="line"><span class="number">30</span>, <span class="number">5.5</span> #</span><br></pre></td></tr></table></figure></div>

<p><strong>默认参数有以下几个注意事项：</strong></p>
<ul>
<li><p>不建议在重载函数时使用默认参数，这会非常容易出错，这里不做过多解释。</p>
</li>
<li><p>默认参数必须是常量或常量表达式，在它们前面有一个赋值运算符<code>=</code>。</p>
</li>
<li><p>一旦为某个形参指定了默认值，那么它后面的所有形参都必须有默认值。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 错误：b有了默认参数，那么b之后的形参都必须有默认参数，而c没有默认参数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n, <span class="type">float</span> b = <span class="number">1.2</span>, <span class="type">char</span> c ,<span class="type">double</span> d=<span class="number">5.2</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; c &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; d &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//正确，第一个有默认参数的形参之后的所有形参都有默认参数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n, <span class="type">float</span> b , <span class="type">char</span> c = <span class="string">&#x27;@&#x27;</span>,<span class="type">double</span> d = <span class="number">5.2</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; c &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; d &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>默认参数应在函数名称最早出现时分配，通常是在函数原型中指定，默认参数只能指定一次。如果函数有声明就会以声明的为准，定义时指出的默认参数就会无效。</p>
<p>如果函数有声明就会以声明的为准，定义时指出的默认参数就会无效。这是因为编译器在处理函数调用时，需要知道函数的参数类型和数量，以及是否有默认值，如果在声明和定义中都给出了默认参数，那么就会造成冲突和混乱。</p>
<p><strong>错误示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//错误示例</span></span><br><span class="line"><span class="comment">//声明</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n = <span class="number">10</span>)</span></span>; <span class="comment">//给n指定了默认值10</span></span><br><span class="line"><span class="comment">//定义</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n = <span class="number">20</span>)</span><span class="comment">//又给n指定了默认值20，即使它们是一样的也是不行</span></span></span><br><span class="line"><span class="function"></span>&#123; </span><br><span class="line">    cout &lt;&lt; n &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="built_in">func</span>(); <span class="comment">//这里应该使用哪个默认值呢？</span></span><br></pre></td></tr></table></figure></div>

<p>这样的代码是不合法的，编译器会报错。正确的做法是只在声明或定义中给出一次默认参数。</p>
<p><strong>正确示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//正确的示例</span></span><br><span class="line"><span class="comment">//声明</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n = <span class="number">10</span>)</span></span>; <span class="comment">//给n指定了默认值10</span></span><br><span class="line"><span class="comment">//定义</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n)</span> <span class="comment">//不再给n指定默认值</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="built_in">func</span>(); <span class="comment">//使用声明中的默认值10</span></span><br></pre></td></tr></table></figure></div>

<p>或者</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//正确的示例</span></span><br><span class="line"><span class="comment">//声明（没有给出默认参数）</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n)</span></span>;</span><br><span class="line"><span class="comment">//定义（给出了默认参数）</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n = <span class="number">10</span>)</span></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//调用（使用定义中的默认值）</span></span><br><span class="line"><span class="built_in">func</span>();</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>当一个实参在一个函数调用中被遗漏时（因为它有默认值)，它后面的所有实参也必须被省略。不能跳过某个实参而给后面的实参赋值。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//带默认参数的函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> n, <span class="type">float</span> b = <span class="number">1.2</span>, <span class="type">char</span> c = <span class="string">&#x27;@&#x27;</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; n &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; c &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 正确</span></span><br><span class="line">    <span class="built_in">func</span>(<span class="number">10</span>); <span class="comment">//相当于func(10, 1.2, &#x27;@&#x27;)</span></span><br><span class="line">	<span class="built_in">func</span>(<span class="number">20</span>, <span class="number">9.8</span>); <span class="comment">//相当于func(20, 9.8, &#x27;@&#x27;)</span></span><br><span class="line">	<span class="built_in">func</span>(<span class="number">30</span>, <span class="number">5.5</span>, <span class="string">&#x27;#&#x27;</span>); <span class="comment">//不使用任何默认值</span></span><br><span class="line">    <span class="comment">//错误</span></span><br><span class="line">    <span class="built_in">func</span>(<span class="number">10</span>, , <span class="string">&#x27;#&#x27;</span>); <span class="comment">//错误！不能跳过第二个参数而给第三个参数赋值</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>默认参数与函数重载可能会产生二义性问题。如果有两个重载函数都可以匹配调用语句，那么编译器会报错。</p>
<p>编译器在处理函数调用时，需要根据实参的类型和数量来确定调用哪个重载函数，如果有多个重载函数都符合条件，那么就会造成歧义。</p>
<p><strong>错误示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//错误的示例</span></span><br><span class="line"><span class="comment">//声明两个重载函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b = <span class="number">10</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义两个重载函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;func(int a, int b) is called&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;func(int a) is called&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="built_in">func</span>(<span class="number">10</span>); <span class="comment">//这里应该调用哪个重载函数呢？</span></span><br></pre></td></tr></table></figure></div>

<p>这样的代码是不合法的，编译器会报错。正确的做法是避免使用默认参数和函数重载产生歧义。</p>
<p><strong>正确示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//正确的示例</span></span><br><span class="line"><span class="comment">//声明两个重载函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">double</span> a)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义两个重载函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">int</span> a)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;func(int a) is called&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(<span class="type">double</span> a)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;func(double a) is called&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用</span></span><br><span class="line"><span class="built_in">func</span>(<span class="number">10</span>); <span class="comment">//调用func(int a)</span></span><br><span class="line"><span class="built_in">func</span>(<span class="number">10.0</span>); <span class="comment">//调用func(double a)</span></span><br></pre></td></tr></table></figure></div></li>
</ul>
<p>有关类中成员函数的重载和默认参数将在类的相关笔记中说明</p>
<h2 id="函数的占位参数"><a href="#函数的占位参数" class="headerlink" title="函数的占位参数"></a>函数的占位参数</h2><hr>
<ul>
<li><p>C++中函数的形参列表可以有占位参数，用来作占位，调用函数时必须填补该位置。</p>
</li>
<li><p>占位参数只有参数类型声明，而没有参数名声明。</p>
</li>
<li><p>一般情况下，在函数体内部无法使用占位参数。占位参数也可以有默认值。</p>
</li>
</ul>
<p>注意事项有以下几点：</p>
<ul>
<li>占位参数不能只有部分参数类型声明，而没有参数名声明，例如 <code>void func(int a, int)</code> 是合法的，但 <code>void func(int, int b)</code> 是不合法的</li>
<li>占位参数一般用于重载运算符或者实现一些特殊功能，不建议在普通函数中使用</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//函数占位参数，占位参数也可以有默认值</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func01</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;this is func&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 有默认参数的占位参数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func02</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b, <span class="type">int</span> = <span class="number">20</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;a + b = &quot;</span> &lt;&lt; a + b &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">func01</span>(<span class="number">10</span>,<span class="number">10</span>); <span class="comment">//占位参数必须填补</span></span><br><span class="line">    </span><br><span class="line">	<span class="built_in">func02</span>(<span class="number">10</span>,<span class="number">20</span>); <span class="comment">// 错误调用，占位参数也是参数，必须传参数</span></span><br><span class="line">    </span><br><span class="line">	<span class="built_in">func02</span>(<span class="number">10</span>,<span class="number">20</span>,<span class="number">30</span>); <span class="comment">//正确调用</span></span><br><span class="line">	<span class="built_in">func02</span>(<span class="number">10</span>,<span class="number">20</span>); <span class="comment">//正确调用</span></span><br><span class="line">	<span class="built_in">func02</span>(<span class="number">10</span>, <span class="number">20</span>, <span class="number">30</span>); <span class="comment">//正确调用</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h1 id="类和对象"><a href="#类和对象" class="headerlink" title="类和对象"></a>类和对象</h1><p>C++中的类是一种用户&#x3D;&#x3D;自定义的数据类型&#x3D;&#x3D;，用于封装数据和函数。类的定义包括数据成员和成员函数，数据成员可以是任何C++数据类型，成员函数可以是普通函数或者操作符重载函数。</p>
<p>&#x3D;&#x3D;类似于<code>struct</code>&#x3D;&#x3D;，当然实际不一样</p>
<p>对象是类的一个实例，它是由类定义的模板创建的具体实体。对象可以访问类中的成员函数和数据成员，可以通过对象来操作类中的数据。</p>
<p>类和对象是面向对象编程的核心概念，它们可以帮助我们更好地组织和管理程序的数据和代码，提高程序的可读性、可维护性和可扩展性。</p>
<p>C++面向对象的三大特征是封装、继承和多态。</p>
<ul>
<li>封装（Encapsulation）：指将数据和操作数据的函数绑定在一起，形成一个类。封装可以隐藏数据和实现细节，防止外部程序直接访问和修改数据，从而提高程序的安全性和可靠性。</li>
<li>继承（Inheritance）：指在一个已有类的基础上，创建一个新类，新类具有原有类的属性和方法。通过继承，可以减少重复代码，提高代码的复用性和可维护性。</li>
<li>多态（Polymorphism）：指同一个函数或方法可以根据不同的对象调用产生不同的行为。多态可以提高程序的灵活性和可扩展性，使程序更易于维护和扩展。</li>
</ul>
<p>这三大特征是C++面向对象编程的核心，也是C++在实现面向对象编程中最重要的手段。</p>
<p><strong>通俗易懂的解释什么是类和对象：</strong></p>
<ul>
<li>当我们看到一只狗时，我们可以想象它是“狗”这个大类（狗这个物种）下的一个“对象”。</li>
<li>狗类有一些属性，如颜色、品种、体型等，也有一些方法，如叫、跑、吃等。</li>
<li>每只狗都具有这些属性和方法，但它们的具体值可能会不同，比如颜色是黑色的、品种是哈士奇的、体型是大型的。</li>
<li>但这些不同的狗都是由狗这个类实例化而来的不同对象。</li>
</ul>
<p>我们可以把类比作一个“图纸”或“模板”，用于描述对象应该具有的属性和方法。而对象则是由这个蓝图创建的具体实例，具有这些属性和方法。就像建筑师会按照图纸来建造房屋一样，我们也可以根据类来创建对象。</p>
<p>另一个比喻是，类就像是一个自定义数据类型，而对象则是这个数据类型的具体实例。就像int是一个数据类型，1、2、3等就是<code>int</code>类型的具体实例一样。</p>
<p><strong>例如：</strong></p>
<ol>
<li>车可以作为对象，属性具有品牌、颜色、速度等，行为有加速、刹车、转弯等，每一辆车都属于车这个大的类。</li>
<li>动物可以作为对象，属性具有种类、生活习性、食物喜好等，行为有奔跑、攀爬、捕猎等，每一种动物都属于动物这个大的类。</li>
<li>商品可以作为对象，属性具有名称、价格、规格等，行为有上架、下架、促销等，每一种商品都属于商品这个大的类。</li>
<li>一个人可以作为对象，属性具有姓名、年龄、身高、体重等，行为有走、跑、跳、吃饭等，每一个人都属于人类这个大的类。</li>
</ol>
<h2 id="类的定义和封装"><a href="#类的定义和封装" class="headerlink" title="类的定义和封装"></a>类的定义和封装</h2><hr>
<p><strong>封装是面向对象编程中的重要概念之一，它的作用和意义主要有以下几个方面：</strong></p>
<ul>
<li>提高安全性：通过封装，我们可以将类的实现细节隐藏起来，只将需要外部访问的接口暴露出来，从而防止外部程序直接访问和修改类的数据，提高程序的安全性和可靠性。</li>
<li>提高可维护性：通过封装，我们可以将类的实现细节和外部接口分离开来，使得在修改类的实现细节时，不会对外部程序产生影响，从而提高程序的可维护性和可扩展性。</li>
<li>简化编程：通过封装，我们可以将复杂的操作封装成一个函数或方法，从而简化编程，减少代码的冗余和复杂度。</li>
<li>提高代码的复用性：通过封装，我们可以将一些通用的功能封装成类或函数，供多个程序复用，从而提高代码的复用性。</li>
</ul>
<p>类似定义<code>struct</code>用户自定义数据类型，定义类的关键字是<code>class</code></p>
<p><strong>基本语法：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> 类名</span><br><span class="line">&#123;</span><br><span class="line">访问权限:</span><br><span class="line">	属性;</span><br><span class="line">	行为;<span class="comment">//行为指函数</span></span><br><span class="line">    ......</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义一个最简单的类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">// 成员函数</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">print</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Hello World!&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="comment">// 数据成员</span></span><br><span class="line">    <span class="type">int</span> num;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 创建一个对象</span></span><br><span class="line">    MyClass obj;</span><br><span class="line">    <span class="comment">// 调用成员函数</span></span><br><span class="line">    obj.<span class="built_in">print</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>解释：</strong></p>
<ul>
<li><p>当我们定义一个类时，我们需要定义它的属性和行为。属性是指该类具有的特征或者状态，行为则是指该类可以执行的操作。</p>
</li>
<li><p>在这个例子中，我们定义了一个叫做&#96;&#96;MyClass&#96;的类，它具有以下属性和行为：</p>
<ul>
<li><p>属性：</p>
<p><code>num</code>：一个整数类型的私有数据成员。</p>
</li>
<li><p>行为：</p>
<p><code>print()</code>：一个公有成员函数，可以输出一条信息到控制台。输出信息就是这个类的行为。</p>
</li>
</ul>
</li>
<li><p>在这个类中，<code>num</code>是一个私有数据成员，外部程序无法直接访问和修改。</p>
</li>
<li><p><code>print()</code>是一个公有成员函数，可以在类的外部直接访问和调用。</p>
</li>
<li><p>调用<code>print</code>函数时，它会输出一条消息到控制台，这条消息是<code>Hello World!</code>。</p>
</li>
</ul>
<p><strong>注意事项和解释：</strong></p>
<ul>
<li><p>公有(<code>public</code>)、私有(<code>private</code>)、保护(<code>protected</code>)是访问权限的修饰符，用于控制类中成员的访问权限。</p>
</li>
<li><p>公有成员可以被类的外部程序访问和调用，私有成员只能被类的内部程序访问和调用，保护成员可以被该类的派生类的内部程序访问和调用。</p>
</li>
<li><p>定义类时，访问权限修饰的顺序建议按照<code>public</code>、<code>protected</code>、<code>private</code>的顺序出现，即<code>public</code>在前，<code>protected</code>在中间，<code>private</code>在后面。</p>
<p>按照公有、保护、私有的顺序来定义类的成员是一种被广泛接受的，可以使代码更加清晰易读，便于他人理解和维护。</p>
</li>
<li><p>在定义一个类时，一般把属性写在前面，成员函数写在后面。按照访问权限的不同，将属性和成员函数分别写在<code>public</code>、<code>protected</code>、<code>private</code>部分。</p>
</li>
<li><p>访问权限的顺序并没有硬性规定，但是通常我们会按照公有、保护、私有的顺序来定义类的成员。具体的实现方式可以根据实际情况进行调整。</p>
</li>
</ul>
<p>在实际编写代码时，具体的代码组织方式应该根据实际情况来确定。</p>
<p><strong>注意事项：</strong></p>
<ul>
<li>类的成员函数可以在类内定义，也可以在类外定义。</li>
<li>如果在类内定义，则默认为内联函数。如果在类外定义，则需要使用作用域解析运算符<code>::</code>指明该函数属于哪个类。</li>
</ul>
<p><strong>类内定义成员函数示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">myFunc</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="comment">// 在类内定义成员函数</span></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p><strong>类外定义成员函数示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">myFunc</span><span class="params">()</span></span>; <span class="comment">// 在类内声明成员函数</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">MyClass::myFunc</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 在类外定义成员函数</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<ul>
<li>如果一个类的成员函数在类外定义，那么在定义之前必须先声明该成员函数，否则编译器会报错。</li>
<li>通常，可以在类的头文件中声明成员函数，在源文件中定义成员函数，以实现类的封装性和可维护性。</li>
</ul>
<h2 id="class和struct的区别"><a href="#class和struct的区别" class="headerlink" title="class和struct的区别"></a><code>class</code>和<code>struct</code>的区别</h2><hr>
<p>在C++中，&#x3D;&#x3D;<code>class</code>和<code>struct</code>本质上是相同的&#x3D;&#x3D;，都可以定义成员变量和成员函数，并且都支持封装、继承和多态等面向对象编程的特性。但是，它们之间有以下几个区别：</p>
<ul>
<li>默认访问权限：在class中，默认的访问权限是<code>private</code>，而在<code>struct</code>中，默认的访问权限是<code>public</code>。因此，在class中定义的成员变量和成员函数是默认无法在类外部访问的，需要通过<code>public</code>关键字进行公开；而在<code>struct</code>中定义的成员变量和成员函数是默认可以在类外部访问的。</li>
<li>继承方式：在<code>class</code>中，继承方式默认是<code>private</code>，即派生类只能通过<code>public</code>成员函数访问基类的成员；而在<code>struct</code>中，继承方式默认是<code>public</code>，即派生类可以直接访问基类的成员。</li>
<li>使用习惯：在使用习惯上，<code>class</code>通常用于定义复杂的数据类型和对象，而<code>struct</code>通常用于定义轻量级的数据类型和数据结构。</li>
</ul>
<p>需要注意的是，以上区别只是默认情况下的差异，在实际使用中，我们可以通过访问权限和继承方式的调整，使<code>class</code>和<code>struct</code>之间的区别也会变得比较模糊。</p>
<h2 id="构造函数"><a href="#构造函数" class="headerlink" title="构造函数"></a>构造函数</h2><hr>
<p>在C++中，构造函数是一种特殊的成员函数，用于&#x3D;&#x3D;初始化类的对象&#x3D;&#x3D;。</p>
<p><strong>注意事项：</strong></p>
<ul>
<li>构造函数的名称必须与类名相同，且不可有返回值类型。</li>
<li>构造函数可以有多个参数，也可以没有参数，以及可以有默认参数。</li>
<li>构造函数可以重载，即同一个类中可以有多个不同参数的构造函数。</li>
<li>构造函数可以在类的内部或外部进行定义，但必须是公有的。</li>
<li>构造函数可以调用其他函数，如成员函数、静态函数等。</li>
<li>如果没有定义构造函数，编译器会提供一个默认的构造函数。</li>
</ul>
<p>以下是一个简单的<strong>示例</strong>，展示了如何定义一个类及其构造函数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">// 构造函数</span></span><br><span class="line">    <span class="built_in">MyClass</span>() </span><br><span class="line">    &#123;</span><br><span class="line">        cout&lt;&lt;<span class="string">&quot;构造函数调用&quot;</span>&lt;&lt;endl;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">    <span class="type">int</span> y;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<ul>
<li>在上面的示例中，<code>MyClass</code>是一个简单的类，包含两个私有成员变量x和y。</li>
<li>当创建<code>MyClass</code>对象时，编译器会自动调用构造函数，从而输出<code>“构造函数调用”</code></li>
</ul>
<p><strong>说明：</strong></p>
<ul>
<li>构造函数还可以用于执行任何必要的预处理或初始化操作，如打开文件或分配内存等。</li>
<li>构造函数可以重载，重载时必须具有不同的参数列表。</li>
<li>构造函数重载时根据提供的参数列表，编译器将自动选择正确的构造函数进行调用。</li>
<li>构造函数对象创建时自动被调用，用于初始化对象的成员变量。</li>
<li>构造函数作用是确保对象被正确地初始化，使程序在使用对象之前具有可预测的状态。</li>
</ul>
<p><strong>例如</strong>，有一个<code>Person</code>类：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">// 构造函数</span></span><br><span class="line">    <span class="built_in">Person</span>(string name, <span class="type">int</span> age) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 成员函数</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Name: &quot;</span> &lt;&lt; name &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Age: &quot;</span> &lt;&lt; age &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    string name;</span><br><span class="line">    <span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 创建对象时调用构造函数进行初始化</span></span><br><span class="line">    <span class="function">Person <span class="title">p</span><span class="params">(<span class="string">&quot;Tom&quot;</span>, <span class="number">20</span>)</span></span>;</span><br><span class="line">    p.<span class="built_in">display</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<ul>
<li>上述例子中，定义了一个<code>Person</code>类，其中定义了一个构造函数，构造函数有两个参数，分别是<code>name</code>和<code>age</code>，用于对对象的数据成员进行初始化。</li>
<li>在<code>main</code>函数中，我们创建了一个<code>Person</code>对象，传入了<code>name</code>和<code>age</code>的值来调用构造函数进行初始化，最后调用<code>display</code>函数输出对象的数据成员。</li>
</ul>
<p><strong>注意事项：</strong></p>
<ul>
<li>如果用户没有定义构造函数，则编译器会自动生成一个默认构造函数。</li>
<li>这个构造函数没有参数，仅仅是对对象的成员变量进行默认的初始化。</li>
<li>如果我们的类需要进行特殊的初始化操作，就需要自己定义构造函数。</li>
<li>构造函数可以用于分配内存，但构造函数本身并不执行内存分配操作。</li>
</ul>
<p><strong>注意事项：</strong></p>
<p>在构造函数中进行内存分配等相关操作，存在一定的风险和限制。不建议在构造函数中进行内存分配等操作。如果确实需要进行这些操作，需要做好异常处理。</p>
<ul>
<li>内存分配操作可能失败。在进行内存分配操作时，如果没有足够的内存可用，分配操作会失败并返回一个空指针。如果构造函数无法处理这种情况，可能会导致程序异常或崩溃。</li>
<li>内存分配操作可能耗费大量时间。在进行内存分配操作时，如果分配的内存较大或较多，可能需要很长时间才能完成。如果构造函数在这段时间内阻塞，可能会导致程序性能下降或超时。</li>
<li>构造函数可能会抛出异常。如果在构造函数中进行内存分配等操作时出现异常，可能会导致对象未能正确创建，从而造成程序错误。</li>
<li>创建一个类对象时，首先会为该对象分配内存空间，然后再调用它的构造函数进行初始化。注意顺序。</li>
</ul>
<p><strong>重载构造函数示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">// 默认构造函数</span></span><br><span class="line">    <span class="built_in">Person</span>() </span><br><span class="line">    &#123;</span><br><span class="line">        name = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        age = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 重载构造函数1，传入姓名</span></span><br><span class="line">    <span class="built_in">Person</span>(string name) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 重载构造函数2，传入姓名和年龄</span></span><br><span class="line">    <span class="built_in">Person</span>(string name, <span class="type">int</span> age) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 成员函数</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Name: &quot;</span> &lt;&lt; name &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Age: &quot;</span> &lt;&lt; age &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    string name;</span><br><span class="line">    <span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 调用不同的构造函数进行初始化</span></span><br><span class="line">    Person p1;</span><br><span class="line">    p1.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p2</span><span class="params">(<span class="string">&quot;Tom&quot;</span>)</span></span>;</span><br><span class="line">    p2.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p3</span><span class="params">(<span class="string">&quot;Jerry&quot;</span>, <span class="number">20</span>)</span></span>;</span><br><span class="line">    p3.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出结果：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Name:</span><br><span class="line">Age: 0</span><br><span class="line">Name: Tom</span><br><span class="line">Age: 0</span><br><span class="line">Name: Jerry</span><br><span class="line">Age: 20</span><br></pre></td></tr></table></figure></div>

<p><strong>带有默认参数的构造函数调用示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">// 带有默认参数的构造函数</span></span><br><span class="line">    <span class="built_in">Person</span>(string name = <span class="string">&quot;&quot;</span>, <span class="type">int</span> age = <span class="number">0</span>) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 成员函数</span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">display</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Name: &quot;</span> &lt;&lt; name &lt;&lt; endl;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Age: &quot;</span> &lt;&lt; age &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    string name;</span><br><span class="line">    <span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 调用带有默认参数的构造函数进行初始化</span></span><br><span class="line">    Person p1;</span><br><span class="line">    p1.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p2</span><span class="params">(<span class="string">&quot;Tom&quot;</span>)</span></span>;</span><br><span class="line">    p2.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p3</span><span class="params">(<span class="string">&quot;Jerry&quot;</span>, <span class="number">20</span>)</span></span>;</span><br><span class="line">    p3.<span class="built_in">display</span>();</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出结果：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Name:</span><br><span class="line">Age: 0</span><br><span class="line">Name: Tom</span><br><span class="line">Age: 0</span><br><span class="line">Name: Jerry</span><br><span class="line">Age: 20</span><br></pre></td></tr></table></figure></div>

<h2 id="析构函数"><a href="#析构函数" class="headerlink" title="析构函数"></a>析构函数</h2><hr>
<p>析构函数是一种特殊类型的成员函数，用于在对象被销毁时进行清理工作。它的作用是在对象生命周期结束时，释放对象所占用的内存资源，包括释放动态分配的内存、关闭文件、释放锁等。</p>
<p><strong>使用和注意事项：</strong></p>
<ul>
<li><p>析构函数的命名必须和类名相同，但需要在名称前添加<code>~</code>。</p>
<p>例如：类名是<code>MyClass</code>，则析构函数的名称是<code>~MyClass</code>。</p>
</li>
<li><p>析构函数不能接有何参数，不能被重载。</p>
</li>
<li><p>当类对象被销毁时，编译器会自动调用相应的析构函数。</p>
</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">MyClass</span>() </span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;构造函数被调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    ~<span class="built_in">MyClass</span>() </span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;析构函数被调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    MyClass obj; <span class="comment">// 创建一个 MyClass 对象</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">构造函数被调用</span><br><span class="line">析构函数被调用</span><br></pre></td></tr></table></figure></div>

<p>在上面的示例中，当创建<code>MyClass</code>对象时，构造函数被调用。当程序结束时，析构函数被自动调用，释放对象所占用的内存资源。</p>
<p><strong>注意事项：</strong></p>
<ul>
<li><p>析构函数可以是虚函数。</p>
<p>如果一个类有虚函数，那么它的析构函数通常也应该是虚函数。这是因为，如果一个类的指针被转换为一个基类指针，并使用基类指针删除指向派生类对象的内存，那么如果析构函数不是虚函数，那么只会调用基类的析构函数，而不会调用派生类的析构函数。这会导致内存泄漏和其他问题。</p>
</li>
<li><p>不要手动调用析构函数。</p>
<p>析构函数应该由编译器自动调用，在对象被删除时自动调用。不要在代码中显式地调用析构函数，这通常会导致不可预测的行为。</p>
</li>
<li><p>析构函数应该处理异常。</p>
<p>析构函数应该能够处理可能发生的异常。如果析构函数抛出异常并且没有被捕获，那么程序会调用 std::terminate()，导致程序异常终止。</p>
</li>
<li><p>在析构函数中不要抛出异常。</p>
<p>虽然析构函数应该能够处理异常，但最好不要在析构函数中抛出异常。因为在抛出异常后，程序通常不会继续执行，导致可能未完成的清理工作无法完成，从而导致资源泄漏等问题。</p>
</li>
<li><p>析构函数中应该释放动态分配的内存。</p>
<p>如果一个类中有动态分配的内存，那么它的析构函数应该释放这些内存。否则，这些内存将会泄漏。</p>
</li>
</ul>
<p>总之，析构函数是一种非常重要的函数，它用于在对象生命周期结束时进行清理工作。正确编写析构函数可以有效地避免内存泄漏和其他问题。</p>
<p>有关虚函数将在之后的内容中提到。</p>
<h2 id="拷贝构造函数"><a href="#拷贝构造函数" class="headerlink" title="拷贝构造函数"></a>拷贝构造函数</h2><hr>
<p>拷贝构造函数是C++中一种特殊的构造函数，它用一个同类的对象来初始化新创建的对象。</p>
<p><strong>拷贝构造函数通常用于以下情况：</strong></p>
<ul>
<li><p>通过使用另一个同类型的对象来初始化新创建的对象。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Point</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x, y;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">//普通有参构造函数</span></span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">int</span> x1, <span class="type">int</span> y1) </span><br><span class="line">    &#123; </span><br><span class="line">        x = x1;</span><br><span class="line">        y = y1; </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 拷贝构造函数</span></span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">const</span> Point &amp;p2) </span><br><span class="line">    &#123;</span><br><span class="line">    	x = p2.x; </span><br><span class="line">   		y = p2.y; </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getX</span><span class="params">()</span>            </span></span><br><span class="line"><span class="function">    </span>&#123;  </span><br><span class="line">        <span class="keyword">return</span> x; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getY</span><span class="params">()</span>            </span></span><br><span class="line"><span class="function">    </span>&#123;  </span><br><span class="line">        <span class="keyword">return</span> y; </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Point <span class="title">p1</span><span class="params">(<span class="number">10</span>, <span class="number">15</span>)</span></span>; <span class="comment">// 这里调用了普通的构造函数</span></span><br><span class="line">    </span><br><span class="line">    Point p2 = p1; <span class="comment">// 这里调用了拷贝构造函数</span></span><br><span class="line">    </span><br><span class="line"> </span><br><span class="line">    <span class="comment">// 访问由构造函数赋值的变量</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;p1.x = &quot;</span> &lt;&lt; p1.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, p1.y = &quot;</span> &lt;&lt; p1.<span class="built_in">getY</span>();</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;\np2.x = &quot;</span> &lt;&lt; p2.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, p2.y = &quot;</span> &lt;&lt; p2.<span class="built_in">getY</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">p1.x = 10, p1.y = 15</span><br><span class="line">p2.x = 10, p2.y = 15</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>复制对象把它作为参数传递给函数，即值传递的方式给函数参数传值</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Point</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x, y;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">int</span> x1, <span class="type">int</span> y1) </span><br><span class="line">    &#123;</span><br><span class="line">        x = x1;</span><br><span class="line">        y = y1;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">const</span> Point&amp; p2) </span><br><span class="line">    &#123;</span><br><span class="line">        x = p2.x;</span><br><span class="line">        y = p2.y;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getX</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getY</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> y;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">displayPoint</span><span class="params">(Point p)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;x = &quot;</span> &lt;&lt; p.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, y = &quot;</span> &lt;&lt; p.<span class="built_in">getY</span>() &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Point <span class="title">p1</span><span class="params">(<span class="number">10</span>, <span class="number">15</span>)</span></span>;</span><br><span class="line">    Point p2 = p1;</span><br><span class="line">    <span class="built_in">displayPoint</span>(p1);</span><br><span class="line">    <span class="built_in">displayPoint</span>(p2);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x = 10, y = 15</span><br><span class="line">x = 10, y = 15</span><br></pre></td></tr></table></figure></div>

<p><strong>解释：</strong></p>
<p>使用值传递的方式传递对象参数，这意味着函数将接收一个新的对象副本，而不是原始对象本身。这个新对象副本将在函数内部使用，而原始对象本身则不会受到任何影响。</p>
<p>在 <code>main</code> 函数中，我们创建了两个 Point 对象 <code>p1</code> 和 <code>p2</code>，并将 <code>p1</code> 复制到 <code>p2</code> 中。然后我们调用 <code>displayPoint</code> 函数两次，将 <code>p1</code> 和 <code>p2</code> 作为参数传递给该函数。在函数内部，我们使用了值传递的方式传递对象参数，因此 <code>displayPoint</code> 函数接收到了 <code>p1</code> 和 <code>p2</code> 的副本，并显示它们的 x 和 y 坐标。</p>
</li>
<li><p>复制对象，值传递方式从函数返回这个对象。</p>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Point</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x, y;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">int</span> x1, <span class="type">int</span> y1) </span><br><span class="line">    &#123;</span><br><span class="line">        x = x1; </span><br><span class="line">        y = y1; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">Point</span>(<span class="type">const</span> Point &amp;p) </span><br><span class="line">    &#123;</span><br><span class="line">        x = p.x; </span><br><span class="line">        y = p.y; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getX</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> x; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getY</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123; </span><br><span class="line">        <span class="keyword">return</span> y; </span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 返回 Point 对象，使用值传递方式</span></span><br><span class="line"><span class="function">Point <span class="title">getPoint</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Point <span class="title">p</span><span class="params">(x, y)</span></span>;</span><br><span class="line">    <span class="keyword">return</span> p;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Point <span class="title">p1</span><span class="params">(<span class="number">10</span>, <span class="number">15</span>)</span></span>;</span><br><span class="line">    <span class="function">Point <span class="title">p2</span><span class="params">(p1)</span></span>; <span class="comment">// 使用拷贝构造函数复制对象</span></span><br><span class="line">    Point p3 = <span class="built_in">getPoint</span>(<span class="number">20</span>, <span class="number">25</span>);</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;p1: x = &quot;</span> &lt;&lt; p1.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, y = &quot;</span> &lt;&lt; p1.<span class="built_in">getY</span>() &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;p2: x = &quot;</span> &lt;&lt; p2.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, y = &quot;</span> &lt;&lt; p2.<span class="built_in">getY</span>() &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;p3: x = &quot;</span> &lt;&lt; p3.<span class="built_in">getX</span>() &lt;&lt; <span class="string">&quot;, y = &quot;</span> &lt;&lt; p3.<span class="built_in">getY</span>() &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">p1: x = 10, y = 15</span><br><span class="line">p2: x = 10, y = 15</span><br><span class="line">p3: x = 20, y = 25</span><br></pre></td></tr></table></figure></div>

<p><strong>解释：</strong></p>
<p>在 <code>main</code> 函数中，我们创建了三个 Point 对象 <code>p1</code>、<code>p2</code> 和 <code>p3</code>。我们使用 <code>p1</code> 来初始化 <code>p2</code>，这里使用了拷贝构造函数。我们还调用了函数 <code>getPoint</code>，该函数使用值传递方式返回一个 Point 对象。在 <code>main</code> 函数中，我们将该返回值赋值给 <code>p3</code>，并将它们的 x 和 y 坐标正确地复制到了它们的副本中，同时使用值传递方式从函数返回对象也没有出现问题。</p>
</li>
</ul>
<h2 id="构造函数定义规则"><a href="#构造函数定义规则" class="headerlink" title="构造函数定义规则"></a>构造函数定义规则</h2><hr>
<ul>
<li><p>默认情况下C++编译器会自动给一个类添加至少3个函数</p>
<ul>
<li>默认构造函数，无参，函数体为空</li>
<li>默认析构函数，无参，函数体为空</li>
<li>默认拷贝构造函数，对属性进行值拷贝</li>
</ul>
</li>
<li><p>构造函数的定义规则：</p>
<ul>
<li>如果用户定义有参构造函数，C++不再提供默认无参构造函数，但是会提供默认拷贝构造函数</li>
<li>如果用户定义拷贝构造函数，C++不在提供其他任何构造函数</li>
</ul>
</li>
<li><p><strong>示例1：</strong></p>
<p>当用户定义有参构造函数时，C++不再提供默认无参构造函数，但是会提供默认拷贝构造函数。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Person</span>(<span class="type">int</span> age) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Person p;<span class="comment">// 编译错误，因为没有默认无参构造函数</span></span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p2</span><span class="params">(<span class="number">18</span>)</span></span>;<span class="comment">// 正确</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p><strong>示例2：</strong></p>
<p>当用户定义拷贝构造函数时，C++不再提供其他任何构造函数。</p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Person</span>(<span class="type">const</span> Person&amp; other) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = other.age;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Person p;<span class="comment">// 编译错误，因为没有默认无参构造函数</span></span><br><span class="line">    </span><br><span class="line">    <span class="function">Person <span class="title">p2</span><span class="params">(p)</span></span>;<span class="comment">// 编译错误，因为没有默认拷贝构造函数</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>示例3：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">int</span> num;</span><br><span class="line">    <span class="type">char</span> ch;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj1; <span class="comment">// 会调用默认构造函数</span></span><br><span class="line">    obj1.num = <span class="number">10</span>;</span><br><span class="line">    obj1.ch = <span class="string">&#x27;a&#x27;</span>;</span><br><span class="line">    MyClass obj2 = obj1; <span class="comment">// 会调用默认拷贝构造函数</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;obj1: &quot;</span> &lt;&lt; obj1.num &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; obj1.ch &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;obj2: &quot;</span> &lt;&lt; obj2.num &lt;&lt; <span class="string">&quot; &quot;</span> &lt;&lt; obj2.ch &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<p><strong>输出结果：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">obj1: 10 a</span><br><span class="line">obj2: 10 a</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h2 id="深拷贝与浅拷贝"><a href="#深拷贝与浅拷贝" class="headerlink" title="深拷贝与浅拷贝"></a>深拷贝与浅拷贝</h2><hr>
<ul>
<li><p><strong>浅拷贝</strong></p>
<ul>
<li>编译器自动提供的拷贝构造函数属于浅拷贝，浅拷贝会将原对象中成员的值逐字节的复制给新对象中对应成员的值。</li>
<li>当类中含有指针成员时，浅拷贝也会逐字节的将原对象的指针成员所指向的地址复制给新对象中对应的指针成员，使得新对象中的对应的指针成员也指向这块地址，使得两个对象中对应的指针成员共用一个地址。</li>
<li>因此，当修改其中一个对象的指针成员时，另一个对象对应的成指针员也会发生改变。</li>
<li>当手动为指针成员开辟存储空间时，浅拷贝会使得两个对象中对应的指针成员指向同一个地址。</li>
<li>手动开辟的内存空间应该手动释放，当使用过浅拷贝的两个对象的生命周期结束时，容易导致对应指针成员指向的地址空间重复释放，从而使得程序崩溃报错。</li>
</ul>
<p>总结：</p>
<ul>
<li><p>对象拷贝后，两个对象的某些指针成员共享同一块内存，当其中一个对象的值改变时，另一个对象的值也会跟着改变，这会导致程序出现难以预料的错误。</p>
</li>
<li><p>当对象被释放时，由于两个对象成员共享同一块内存，可能会导致重复释放内存的问题，从而导致程序崩溃。</p>
</li>
<li><p>当对象中存在动态内存分配的指针时，由于两个对象共享同一块内存，可能会导致指针指向的内存被重复释放的问题，从而导致程序崩溃。</p>
</li>
<li><p>因此，在设计类时，如果类的成员中存在指针或动态内存分配的情况，应该尽量避免使用浅拷贝，而应该使用深拷贝来避免上述问题。</p>
</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">preson</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="type">int</span> age;</span><br><span class="line">	<span class="type">int</span>* height;</span><br><span class="line"></span><br><span class="line">	<span class="built_in">preson</span>(<span class="type">int</span> m_age,<span class="type">int</span> m_height)<span class="comment">//preson的有参构造函数</span></span><br><span class="line">	&#123;</span><br><span class="line">		age = m_age;</span><br><span class="line">		height = <span class="keyword">new</span> <span class="built_in">int</span>(m_height);<span class="comment">//堆区开辟的内存应该手动释放</span></span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;preson的有参构造函数调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">preson</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;preson的析构函数调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="comment">//浅拷贝会导致同一块内存重复释放，导致程序异常</span></span><br><span class="line">		<span class="keyword">if</span> (height != <span class="literal">NULL</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">delete</span> height;</span><br><span class="line">			height = <span class="literal">NULL</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">preson <span class="title">p1</span><span class="params">(<span class="number">18</span>, <span class="number">160</span>)</span></span>;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;p1年龄的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)&amp;p1.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p1的年龄：&quot;</span> &lt;&lt; p1.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;   p1身高的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)p1.height </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p1的身高：&quot;</span> &lt;&lt; *p1.height &lt;&lt; endl;</span><br><span class="line">    </span><br><span class="line">	preson p2 = p1;<span class="comment">//编译器自动提供拷贝构造函数，浅拷贝</span></span><br><span class="line">    </span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;p2年龄的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)&amp;p2.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p2的年龄：&quot;</span> &lt;&lt; p2.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;   p2身高的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)p2.height </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p2的身高：&quot;</span> &lt;&lt; *p2.height </span><br><span class="line">        &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p><strong>深拷贝</strong></p>
<p>深拷贝是指在对象复制时，将一个对象的值复制到另一个新的对象中，这两个对象有不同的地址，它们各自占用不同的内存空间，这种复制方式可以避免浅拷贝的问题，同时也能保证原对象和新对象是独立的，互相不会影响。</p>
<p>深拷贝通常需要手动实现，主要是在对象中存在指针或动态内存分配的情况下，需要手动复制指针指向的内存空间，而不是简单的复制指针本身。</p>
<p>在实现深拷贝时，可以通过以下几种方式：</p>
<ol>
<li>手动实现复制构造函数和赋值运算符重载函数，其中包括创建新的内存空间并复制原对象的值，释放原有内存空间等操作。</li>
<li>使用C++11中提供的智能指针（如<code>std::shared_ptr</code>、<code>std::unique_ptr</code>等），这些指针会自动管理内存，可以避免手动释放内存的问题。</li>
<li>使用标准库中的容器类（如<code>std::vector</code>、<code>std::list</code>等），这些容器类会自动管理内存，可以避免手动释放内存的问题。</li>
</ol>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="type">int</span> age;</span><br><span class="line">	<span class="type">int</span>* height;</span><br><span class="line"></span><br><span class="line">	<span class="built_in">person</span>(<span class="type">int</span> m_age,<span class="type">int</span> m_height)<span class="comment">//person的有参构造函数</span></span><br><span class="line">	&#123;</span><br><span class="line">		age = m_age;</span><br><span class="line">		height = <span class="keyword">new</span> <span class="built_in">int</span>(m_height);<span class="comment">//堆区开辟的内存应该手动释放</span></span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;person的有参构造函数调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="built_in">person</span>(<span class="type">const</span> person &amp;p)<span class="comment">//person的拷贝构造，手动实现深拷贝</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;拷贝构造函数的调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">		age = p.age;</span><br><span class="line">		<span class="comment">//height = p.height;编译器自动提供的拷贝构造实现方式</span></span><br><span class="line">		height = <span class="keyword">new</span> <span class="built_in">int</span>(*p.height);<span class="comment">//深拷贝</span></span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">person</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;person的析构函数调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="comment">//浅拷贝会导致同一块内存重复释放，导致程序异常</span></span><br><span class="line">		<span class="keyword">if</span> (height != <span class="literal">NULL</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">delete</span> height;</span><br><span class="line">			height = <span class="literal">NULL</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">person <span class="title">p1</span><span class="params">(<span class="number">18</span>, <span class="number">160</span>)</span></span>;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;p1年龄的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)&amp;p1.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p1的年龄：&quot;</span> &lt;&lt; p1.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;   p1身高的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)p1.height </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p1的身高：&quot;</span> &lt;&lt; *p1.height &lt;&lt; endl;</span><br><span class="line">    </span><br><span class="line">	person p2 = p1;<span class="comment">//编译器自动提供拷贝构造函数，浅拷贝</span></span><br><span class="line">    </span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;p2年龄的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)&amp;p2.age </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p2的年龄：&quot;</span> &lt;&lt; p2.age &lt;</span><br><span class="line">        &lt; <span class="string">&quot;   p2身高的地址：&quot;</span> &lt;&lt; (<span class="type">int</span>)p2.height </span><br><span class="line">        &lt;&lt; <span class="string">&quot;  p2的身高：&quot;</span> &lt;&lt; *p2.height &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h2 id="初始化列表"><a href="#初始化列表" class="headerlink" title="初始化列表"></a>初始化列表</h2><hr>
<p>C++中的初始化列表是用来初始化类成员变量的一种常用方式。</p>
<p>它的语法形式是在构造函数的参数列表后面使用冒号分隔符，然后列出成员变量和它们的初始值，<strong>如下所示：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">MyClass</span>(<span class="type">int</span> a, <span class="type">int</span> b) : <span class="built_in">var1</span>(a), <span class="built_in">var2</span>(b) </span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> var1;</span><br><span class="line">    <span class="type">int</span> var2;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p>在上面的代码中，构造函数的参数列表是 <code>(int a, int b)</code>，冒号后面的初始化列表是 <code>: var1(a), var2(b)</code>。它的作用是将构造函数的参数 <code>a</code> 和 <code>b</code> 分别赋值给成员变量 <code>var1</code> 和 <code>var2</code>。</p>
<ul>
<li>使用初始化列表的好处是可以提高代码的执行效率，因为它避免了在构造函数内部进行赋值操作的额外开销。</li>
<li>初始化列表还可以用来初始化常量成员变量和引用类型成员变量，因为这些成员变量只能在初始化列表中被赋值初始化。</li>
<li>需要注意的是，初始化列表中的成员变量顺序应该和类定义中的顺序一致，否则会导致编译错误。</li>
<li>此外，如果某个成员变量没有在初始化列表中被赋值，它将被默认初始化，这通常是不可预知的，因此建议在初始化列表中为所有成员变量赋初始值。</li>
</ul>
<h2 id="静态成员"><a href="#静态成员" class="headerlink" title="静态成员"></a>静态成员</h2><hr>
<ul>
<li><p>静态成员变量：</p>
<p>静态成员变量：在类中定义的静态变量，它属于整个类而不是某个对象，所有对象共享同一份数据。它可以通过类名或对象名访问，但必须在类外初始化。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Test</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">static</span> <span class="type">int</span> s_var; <span class="comment">// 声明一个静态成员变量 </span></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; s_var &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">static</span> <span class="type">int</span> d;<span class="comment">//私有静态成员变量</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> Test::s_var = <span class="number">30</span>; <span class="comment">// 必须再在类外初始化</span></span><br><span class="line"><span class="type">int</span> Test::d = <span class="number">40</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Test t1;</span><br><span class="line">    cout &lt;&lt; t1.s_var &lt;&lt; endl;<span class="comment">//通过对象访问</span></span><br><span class="line">    cout &lt;&lt; Test::s_var &lt;&lt; endl;<span class="comment">//通过类名作用域访问</span></span><br><span class="line">    <span class="comment">//cout &lt;&lt; Test::d &lt;&lt; endl;//私有静态成员变量类外无法访问</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;	</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>静态成员函数</p>
<ul>
<li>静态成员函数不依赖于任何类对象，因此可以在没有类对象的情况下被调用。</li>
<li>静态成员函数只能访问静态成员变量和静态成员函数。因为非静态成员变量和函数是依赖于类对象的，因此在没有类对象的情况下无法访问。</li>
<li>静态成员函数可以直接通过类名来调用，也可以通过对象来调用。</li>
<li>静态成员函数也有访问权限，<code>private</code>作用域下的无法访问</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> myVar;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">static</span> <span class="type">int</span> myStaticVar;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">MyClass</span>(<span class="type">int</span> var) </span><br><span class="line">    &#123;</span><br><span class="line">        myVar = var;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">myFunction</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;myVar: &quot;</span> &lt;&lt; myVar &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">myStaticFunction</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;myStaticVar: &quot;</span> &lt;&lt; myStaticVar &lt;&lt; endl;</span><br><span class="line">        <span class="comment">// cout &lt;&lt; &quot;myVar: &quot; &lt;&lt; myVar &lt;&lt; endl;// 错误：无法访问非静态成员变量myVar</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> MyClass::myStaticVar = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">MyClass <span class="title">obj1</span><span class="params">(<span class="number">10</span>)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// obj1.myStaticFunction();// 错误：不能通过对象调用静态成员函数</span></span><br><span class="line"></span><br><span class="line">    MyClass::<span class="built_in">myStaticFunction</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h2 id="this指针"><a href="#this指针" class="headerlink" title="this指针"></a><code>this</code>指针</h2><hr>
<ul>
<li><p>在C++中，this指针是一个特殊的指针，它指向当前对象的地址。this指针在成员函数内部使用，它可以访问当前对象的成员变量和成员函数。</p>
<p>使用this指针可以避免成员变量和局部变量的名字冲突，并且可以方便地在成员函数中访问对象的成员变量。</p>
<p><strong>使用示例：</strong></p>
<p>在成员函数内部，可以使用this指针来访问对象的成员变量和成员函数。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setValue</span><span class="params">(<span class="type">int</span> value)</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;value = value; <span class="comment">// 使用this指针访问成员变量</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getValue</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>-&gt;value; <span class="comment">// 使用this指针访问成员变量</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> value;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj;</span><br><span class="line">    obj.<span class="built_in">setValue</span>(<span class="number">10</span>);</span><br><span class="line">    cout &lt;&lt; obj.<span class="built_in">getValue</span>() &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在上面的示例中，我们创建了一个<code>MyClass</code>对象<code>obj</code>，并调用了<code>setValue</code>函数来设置<code>obj</code>的<code>value</code>成员变量的值为<code>10</code>，然后调用<code>getValue</code>函数来获取<code>obj</code>的v<code>alue</code>成员变量的值并输出。</p>
<p><strong>错误示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setValue</span><span class="params">(<span class="type">int</span> value)</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        value = value; <span class="comment">// 错误的使用方式，不使用this指针</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getValue</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> value; <span class="comment">// 错误的使用方式，不使用this指针</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> value;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj;</span><br><span class="line">    obj.<span class="built_in">setValue</span>(<span class="number">10</span>);</span><br><span class="line">    cout &lt;&lt; obj.<span class="built_in">getValue</span>() &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在上面的错误示例中，我们在<code>setValue</code>和g<code>etValue</code>函数中没有使用this指针来访问成员变量，而是直接使用了函数参数<code>value</code>和成员变量<code>value</code>。这样会导致函数参数<code>value</code>和成员变量<code>value</code>混淆，无法正确访问对象的成员变量。</p>
</li>
</ul>
<h2 id="const修饰的成员函数和对象"><a href="#const修饰的成员函数和对象" class="headerlink" title="const修饰的成员函数和对象"></a><code>const</code>修饰的成员函数和对象</h2><hr>
<p>&#x3D;&#x3D;<code>this</code>指针的本质：&#x3D;&#x3D;<code>className * const this</code>，<code>this</code>指针的指向不可以修改</p>
<ul>
<li><code>const</code>修饰的成员函数：<ul>
<li>函数函数名后面加上<code>const</code>，称这个成员函数为常函数</li>
<li>常成员函数内不可以修改成员属性</li>
<li>成员属性声明时加上<code>mutable</code>关键字后在常成员函数中可以修改</li>
</ul>
</li>
</ul>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setValue</span><span class="params">(<span class="type">int</span> value)</span> </span></span><br><span class="line"><span class="function">    </span>&#123; </span><br><span class="line">        m_value = value; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getValue</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123; </span><br><span class="line">        <span class="keyword">return</span> m_value; </span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">mutable</span> <span class="type">int</span> m_value; <span class="comment">// mutable 修饰的变量</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">const</span> MyClass obj; <span class="comment">// 声明一个 const 对象</span></span><br><span class="line">    <span class="type">int</span> value = obj.<span class="built_in">getValue</span>(); <span class="comment">// 可以调用 const 成员函数</span></span><br><span class="line">    <span class="comment">// obj.setValue(10); // 错误：不能调用非 const 成员函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>相当与将<code>className * const this</code>改成<code>const className * const this</code>，这样<code>this</code>指针的指向和<code>this</code>指针指向的值都无法修改了</p>
<ul>
<li><p><strong><code>const</code>修饰的对象：</strong></p>
<ul>
<li>声明对象前加上<code>const</code>关键字，则该对象定义为常对象</li>
<li>常对象只能调用常成员函数</li>
</ul>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">setValue</span><span class="params">(<span class="type">int</span> value)</span> </span></span><br><span class="line"><span class="function">    </span>&#123; </span><br><span class="line">        m_value = value; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getValue</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123; </span><br><span class="line">        <span class="keyword">return</span> m_value; </span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> m_value;</span><br><span class="line">    <span class="keyword">mutable</span> <span class="type">int</span> n_value; <span class="comment">// mutable 修饰的变量</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">const</span> MyClass obj; <span class="comment">// 声明一个常对象</span></span><br><span class="line">    <span class="type">int</span> value = obj.<span class="built_in">getValue</span>(); <span class="comment">// 可以调用常成员函数</span></span><br><span class="line">    <span class="comment">// obj.setValue(10); // 错误：常对象不能调用非常成员函数</span></span><br><span class="line">    obj.n_value = <span class="number">100</span>;<span class="comment">//常对象可以修改 mutable 修饰的变量</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h2 id="成员函数重载"><a href="#成员函数重载" class="headerlink" title="成员函数重载"></a>成员函数重载</h2><hr>
<h3 id="普通重载"><a href="#普通重载" class="headerlink" title="普通重载"></a>普通重载</h3><p>当一个类中有多个成员函数名称相同但参数列表不同的函数时，就会发生类成员函数的重载。</p>
<p>C++中，类成员函数重载的规则和普通函数重载的规则是一样的，必须满足函数名称相同但参数列表不同的条件。</p>
<p>下面是一个类成员函数重载的<strong>示例</strong>：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">cppCopy codeclass MyClass </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;foo(int x) called with &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">double</span> x)</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;foo(double x) called with &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj;</span><br><span class="line">    obj.<span class="built_in">foo</span>(<span class="number">1</span>);      <span class="comment">// 调用foo(int x)</span></span><br><span class="line">    obj.<span class="built_in">foo</span>(<span class="number">1.234</span>);  <span class="comment">// 调用foo(double x)</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h3 id="常量性重载"><a href="#常量性重载" class="headerlink" title="常量性重载"></a>常量性重载</h3><hr>
<p>常量性重载是指一个成员函数有常量和非常量两种版本，常量版本的成员函数在其函数名后面加上 <code>const</code> 关键字，用于处理常量对象。</p>
<p>常量性重载函数可以让<code>const</code>对象调用特定的函数，并且不能修改对象的状态。</p>
<p>下面是一个常量性重载的<strong>示例</strong>：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">cppCopy codeclass MyClass </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;foo() called&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;const foo() called&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj1;</span><br><span class="line">    obj1.<span class="built_in">foo</span>();       <span class="comment">// 调用 foo()</span></span><br><span class="line">    <span class="type">const</span> MyClass obj2;</span><br><span class="line">    obj2.<span class="built_in">foo</span>();       <span class="comment">// 调用 const foo()</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>注意，常量性重载的成员函数需要保证其不会修改对象的状态，所以在常量成员函数中只能调用其他常量成员函数或常量数据成员，不能调用非常量成员函数或修改数据成员。</p>
<p>常量性重载函数中，常量类对象可以调用常量版本的成员函数，而非常量类对象则只能调用非常量版本的成员函数。</p>
<p>举个例子，假设我们有一个名为 <code>MyClass</code> 的类，它有两个版本的成员函数 <code>foo()</code>：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">cppCopy codeclass MyClass </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;foo() called&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;const foo() called&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p>现在假设我们有一个常量类对象 <code>const MyClass obj1;</code> 和一个非常量类对象 <code>MyClass obj2;</code>，它们都可以调用 <code>foo()</code> 成员函数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cppCopy codeobj1.<span class="built_in">foo</span>(); <span class="comment">// 调用 const foo()</span></span><br><span class="line">obj2.<span class="built_in">foo</span>(); <span class="comment">// 调用 foo()</span></span><br></pre></td></tr></table></figure></div>

<p>在普通函数的函数名后面加上 <code>const</code> 关键字是没有意义的。因为 <code>const</code> 关键字用于修饰类的成员函数，它表示该成员函数不会修改类的成员变量。而普通函数没有成员变量，所以 <code>const</code> 关键字对它们没有意义。</p>
<p>在普通函数中，如果要实现类似于常量性重载的效果，可以使用函数重载。例如，可以编写一个非常量版本和一个常量版本的同名函数，分别用于处理非常量对象和常量对象。</p>
<p><strong>例如：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">cppCopy codevoid <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;foo(int x) called with &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;const foo(const int x) called with &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>这样，可以让非常量对象调用非常量版本的函数，常量对象调用常量版本的函数。</p>
<p>在普通函数的函数名后面加上 <code>const</code> 是语法上不正确的，编译器在编译时会报错。</p>
<p>这是因为 <code>const</code> 关键字只能用于类的成员函数中，表示该成员函数不会修改类的成员变量。普通函数没有成员变量，所以在普通函数名后面加上 <code>const</code> 关键字是没有意义的，也是非法的。</p>
<p>以下是一个示例，试图在普通函数中添加 <code>const</code> 关键字：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">cppCopy codevoid <span class="title">foo</span><span class="params">(<span class="type">const</span> <span class="type">int</span> x)</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>编译器会报错，因为它不知道如何处理这个语句，它既不是一个成员函数，也不是一个正确的普通函数。</p>
<h2 id="友元"><a href="#友元" class="headerlink" title="友元"></a>友元</h2><hr>
<ul>
<li>友元是C++中的一种特殊关系，它允许一个类的非成员函数或另一个类的成员函数访问该类的私有成员变量和函数。</li>
</ul>
<p><strong>语法：</strong></p>
<ul>
<li>友元函数的声明：在类的内部，使用关键字<code>friend</code>声明一个函数为友元函数，如下所示：</li>
</ul>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//friend void friendFunc();//也可以在这里声明</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">friend</span> <span class="type">void</span> <span class="title">friendFunc</span><span class="params">()</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<ul>
<li>友元类的声明：在类的内部，使用关键字<code>friend</code>声明一个类为友元类，如下所示：</li>
</ul>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//friend class FriendClass;//也可以在这里声明</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">friend</span> <span class="keyword">class</span> <span class="title class_">FriendClass</span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<h3 id="全局函数做友元"><a href="#全局函数做友元" class="headerlink" title="全局函数做友元"></a>全局函数做友元</h3><hr>
<p><strong>示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">friend</span> <span class="type">void</span> <span class="title">setNum</span><span class="params">(MyClass&amp; obj, <span class="type">int</span> n)</span></span>;<span class="comment">//将全局函数 setNum 声明为友元</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> num;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">MyClass</span>() : <span class="built_in">num</span>(<span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">setNum</span><span class="params">(MyClass&amp; obj, <span class="type">int</span> n)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    obj.num = n;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyClass obj;</span><br><span class="line">    <span class="built_in">setNum</span>(obj, <span class="number">10</span>);</span><br><span class="line">    cout &lt;&lt; obj.num &lt;&lt; endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在上面的代码中，我们定义了一个名为<code>MyClass</code>的类，其中包含一个私有变量<code>num</code>。</p>
<p>然后我们声明了一个全局函数<code>setNum</code>作为<code>MyClass</code>的友元函数，这样<code>setNum</code>就可以访问<code>MyClass</code>的私有变量<code>num</code>了。</p>
<p>在主函数中我们创建了一个<code>MyClass</code>对象obj，然后调用<code>setNum</code>函数并将<code>obj</code>和<code>10</code>作为参数传递进去，最后输出<code>obj</code>的<code>num</code>值，即得到了10。</p>
<h3 id="类做友元"><a href="#类做友元" class="headerlink" title="类做友元"></a>类做友元</h3><hr>
<p><strong>示例：</strong>其中类<code>B</code>被声明为类A的友元，可以访问类<code>A</code>的私有成员变量<code>x</code></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">friend</span> <span class="keyword">class</span> <span class="title class_">B</span>; <span class="comment">// 类B是类A的友元</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">A</span>(<span class="type">int</span> value) : <span class="built_in">x</span>(value) </span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">printX</span><span class="params">(A &amp; a)</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;x is &quot;</span> &lt;&lt; a.x &lt;&lt; std::endl; <span class="comment">// 可以访问类A的私有成员变量x</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">A <span class="title">a</span><span class="params">(<span class="number">10</span>)</span></span>;</span><br><span class="line">    B b;</span><br><span class="line">    b.<span class="built_in">printX</span>(a); <span class="comment">// 输出：x is 10</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h3 id="成员函数做友元"><a href="#成员函数做友元" class="headerlink" title="成员函数做友元"></a>成员函数做友元</h3><hr>
<p><strong>示例：：</strong>其中类<code>A</code>的成员函数<code>funcA()</code>是类<code>B</code>的友元函数，可以访问类<code>B</code>的私有成员变量</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">B</span>; <span class="comment">// 前置声明</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">funcA</span><span class="params">(B&amp; objB)</span></span>; <span class="comment">// 声明 void funcA 函数，用于访问 B 中的私有成员</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">friend</span> <span class="type">void</span> <span class="title">A::funcA</span><span class="params">(B&amp; objB)</span></span>; <span class="comment">// 声明A的成员函数为友元函数</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">B</span>(<span class="type">int</span> x): <span class="built_in">x</span>(x) </span><br><span class="line">    &#123;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">A::funcA</span><span class="params">(B&amp; objB)</span> <span class="comment">//类外定义void funcA 函数</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;B的私有成员变量x的值为：&quot;</span> &lt;&lt; objB.x &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">B <span class="title">objB</span><span class="params">(<span class="number">10</span>)</span></span>;</span><br><span class="line">    A objA;</span><br><span class="line">    objA.<span class="built_in">funcA</span>(objB); <span class="comment">// 调用A的成员函数，输出B的私有成员变量x的值</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>输出：</strong></p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">B的私有成员变量x的值为：10</span><br></pre></td></tr></table></figure></div>

<h1 id="运算符重载"><a href="#运算符重载" class="headerlink" title="运算符重载"></a>运算符重载</h1><p>概念：对已有运算符进行定义，赋予其另一种功能，以适应不同数据类型</p>
<h2 id="四则运算符重载"><a href="#四则运算符重载" class="headerlink" title="四则运算符重载"></a>四则运算符重载</h2><hr>
<p><code>operator+</code></p>
<p><code>operator-</code></p>
<p><code>operator*</code></p>
<p><code>operator/</code></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Vector</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">float</span> x, y, z;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 构造函数</span></span><br><span class="line">    <span class="built_in">Vector</span>(<span class="type">float</span> x = <span class="number">0</span>, <span class="type">float</span> y = <span class="number">0</span>, <span class="type">float</span> z = <span class="number">0</span>) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;x = x;</span><br><span class="line">        <span class="keyword">this</span>-&gt;y = y;</span><br><span class="line">        <span class="keyword">this</span>-&gt;z = z;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载&quot;+&quot;运算符</span></span><br><span class="line">    Vector <span class="keyword">operator</span>+(<span class="type">const</span> Vector&amp; v) <span class="type">const</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">Vector</span>(x + v.x, y + v.y, z + v.z);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载&quot;-&quot;运算符</span></span><br><span class="line">    Vector <span class="keyword">operator</span>-(<span class="type">const</span> Vector&amp; v) <span class="type">const</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">Vector</span>(x - v.x, y - v.y, z - v.z);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载&quot;&lt;&lt;&quot;运算符</span></span><br><span class="line">    <span class="keyword">friend</span> ostream&amp; <span class="keyword">operator</span>&lt;&lt;(ostream&amp; os, <span class="type">const</span> Vector&amp; v) </span><br><span class="line">    &#123;</span><br><span class="line">        os &lt;&lt; <span class="string">&quot;(&quot;</span> &lt;&lt; v.x &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.y &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.z &lt;&lt; <span class="string">&quot;)&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> os;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//全局 重载&quot;*&quot;运算符</span></span><br><span class="line">Vector <span class="keyword">operator</span>*(<span class="type">const</span> Vector&amp; v1, <span class="type">const</span> Vector&amp; v2)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Vector</span>(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//全局 重载&quot;/&quot;运算符</span></span><br><span class="line">Vector <span class="keyword">operator</span>/(<span class="type">const</span> Vector&amp; v1, <span class="type">const</span> Vector&amp; v2)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 检查除数是否为0</span></span><br><span class="line">    <span class="keyword">if</span> (scalar == <span class="number">0</span>) </span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Error: Division by zero!&quot;</span> &lt;&lt; endl;</span><br><span class="line">        <span class="keyword">return</span> v;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Vector</span>(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);    <span class="comment">// 执行除法运算</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Vector <span class="title">v1</span><span class="params">(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>)</span></span>;</span><br><span class="line">    <span class="function">Vector <span class="title">v2</span><span class="params">(<span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>)</span></span>;</span><br><span class="line">    Vector v3 = v1 + v2;</span><br><span class="line">    Vector v4 = v1 - v2;</span><br><span class="line">    Vector v5 = v1 * v2;</span><br><span class="line">    Vector v6 = v1 / v2;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v1 = &quot;</span> &lt;&lt; v1 &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v2 = &quot;</span> &lt;&lt; v2 &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v1 + v2 = &quot;</span> &lt;&lt; v3 &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v1 - v2 = &quot;</span> &lt;&lt; v4 &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v1 * v2 = &quot;</span> &lt;&lt; v5 &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;v1 / v2 = &quot;</span> &lt;&lt; v6 &lt;&lt; endl;  </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="左移（"><a href="#左移（" class="headerlink" title="左移（&lt;&lt;）运算符重载"></a>左移（<code>&lt;&lt;</code>）运算符重载</h2><hr>
<p>左移运算符重载不可以定义在类中作为类的成员函数，只能定义为全局函数，如果定义在类中，需要加上<code>friend</code>关键字，但默认是全局函数</p>
<p><code>cout</code>是一个<code>ostream</code>对象，重载时需要指定参数类型，并返回这个流对象，使得<code>&lt;&lt;</code>可以链式调用。</p>
<p><strong>代码示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Vector</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">float</span> x, y, z;</span><br><span class="line">	<span class="keyword">friend</span> ostream&amp; <span class="keyword">operator</span>&lt;&lt;(ostream&amp; os, <span class="type">const</span> Vector&amp; v) </span><br><span class="line">	&#123;</span><br><span class="line">		os &lt;&lt; <span class="string">&quot;(&quot;</span> &lt;&lt; v.x &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.y &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.z &lt;&lt; <span class="string">&quot;)&quot;</span>;</span><br><span class="line">    	<span class="keyword">return</span> os;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>或者</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Vector</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">friend</span> ostream&amp; <span class="keyword">operator</span>&lt;&lt;(ostream&amp; os, <span class="type">const</span> Vector&amp; v) </span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">float</span> x, y, z;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ostream&amp; <span class="keyword">operator</span>&lt;&lt;(ostream&amp; os, <span class="type">const</span> Vector&amp; v) </span><br><span class="line">&#123;</span><br><span class="line">	os &lt;&lt; <span class="string">&quot;(&quot;</span> &lt;&lt; v.x &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.y &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; v.z &lt;&lt; <span class="string">&quot;)&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> os;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="自增（-）运算符重载"><a href="#自增（-）运算符重载" class="headerlink" title="自增（++）运算符重载"></a>自增（<code>++</code>）运算符重载</h2><hr>
<p>前置++运算符重载，要返回引用，同样对于前置<code>--</code>运算符也一样</p>
<p><strong>重载前置自增运算符（++）：</strong></p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Counter</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> count;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Counter</span>(<span class="type">int</span> initialCount = <span class="number">0</span>) : <span class="built_in">count</span>(initialCount) &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载前置自增运算符</span></span><br><span class="line">    Counter&amp; <span class="keyword">operator</span>++() </span><br><span class="line">    &#123;</span><br><span class="line">        count++;</span><br><span class="line">        <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getCount</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> count;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Counter <span class="title">c</span><span class="params">(<span class="number">5</span>)</span></span>;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Initial count: &quot;</span> &lt;&lt; c.<span class="built_in">getCount</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    ++c;  <span class="comment">// 使用前置自增运算符</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Count after increment: &quot;</span> &lt;&lt; c.<span class="built_in">getCount</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>后置++运算符重载，要返回值，同样对于前置<code>--</code>运算符也一样</p>
<p><strong>重载后置自增运算符（++）：</strong></p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Counter</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span> count;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Counter</span>(<span class="type">int</span> initialCount = <span class="number">0</span>) : <span class="built_in">count</span>(initialCount) &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载后置自增运算符</span></span><br><span class="line">    Counter <span class="keyword">operator</span>++(<span class="type">int</span>) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="function">Counter <span class="title">temp</span><span class="params">(count)</span></span>;  <span class="comment">// 创建临时对象保存当前值</span></span><br><span class="line">        count++;</span><br><span class="line">        <span class="keyword">return</span> temp;  <span class="comment">// 返回保存的临时对象</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getCount</span><span class="params">()</span> <span class="type">const</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> count;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">Counter <span class="title">c</span><span class="params">(<span class="number">5</span>)</span></span>;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Initial count: &quot;</span> &lt;&lt; c.<span class="built_in">getCount</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    Counter d = c++;  <span class="comment">// 使用后置自增运算符</span></span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Count after increment: &quot;</span> &lt;&lt; c.<span class="built_in">getCount</span>() &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;Value before increment: &quot;</span> &lt;&lt; d.<span class="built_in">getCount</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><strong>重载前置自增运算符时的注意事项：</strong></p>
<ul>
<li>前置自增运算符的重载函数返回引用，以便允许连续的自增操作。</li>
<li>在重载前置自增运算符时，首先对对象进行自增操作，然后返回自增后的对象。</li>
</ul>
<p><strong>重载后置自增运算符时的注意事项：</strong></p>
<ul>
<li>后置自增运算符的重载函数需要使用一个额外的整型参数（<code>int</code>）来区分后置自增运算符重载函数和前置自增运算符重载函数。</li>
<li>在重载后置自增运算符时，首先创建一个临时对象来保存自增前的对象值，然后对对象进行自增操作，最后返回保存的临时对象。</li>
</ul>
<p>在使用重载后置自增运算符时，需要注意后置自增运算符返回的是自增之前的值，而不是自增之后的值。</p>
<p>因此，在示例代码中，将后置自增运算符的返回值存储在一个新的<code>Counter对</code>象中（变量<code>d</code>），以便打印出自增之前的值。</p>
<h2 id="赋值（-）运算符重载（深拷贝）"><a href="#赋值（-）运算符重载（深拷贝）" class="headerlink" title="赋值（=）运算符重载（深拷贝）"></a>赋值（<code>=</code>）运算符重载（深拷贝）</h2><hr>
<p>当重载赋值运算符<code>=</code>时，要确保进行的是深拷贝，以防止内存重复释放。</p>
<p><strong>代码示例：</strong></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="type">int</span>* data; <span class="comment">// 指针成员，动态分配的数据</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">MyClass</span>(<span class="type">int</span> value) </span><br><span class="line">    &#123;</span><br><span class="line">        data = <span class="keyword">new</span> <span class="type">int</span>;</span><br><span class="line">        *data = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 拷贝构造函数</span></span><br><span class="line">    <span class="built_in">MyClass</span>(<span class="type">const</span> MyClass&amp; other)</span><br><span class="line">    &#123;</span><br><span class="line">        data = <span class="keyword">new</span> <span class="type">int</span>;</span><br><span class="line">        *data = *(other.data);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 赋值运算符重载</span></span><br><span class="line">    MyClass&amp; <span class="keyword">operator</span>=(<span class="type">const</span> MyClass&amp; other) </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">// 检查自我赋值</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">this</span> == &amp;other)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 执行深拷贝</span></span><br><span class="line">        <span class="keyword">delete</span> data; <span class="comment">// 释放原有内存</span></span><br><span class="line">        data = <span class="keyword">new</span> <span class="type">int</span>;</span><br><span class="line">        *data = *(other.data);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ~<span class="built_in">MyClass</span>() </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">delete</span> data;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">getData</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> *data;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="function">MyClass <span class="title">obj1</span><span class="params">(<span class="number">5</span>)</span></span>;</span><br><span class="line">    <span class="function">MyClass <span class="title">obj2</span><span class="params">(<span class="number">10</span>)</span></span>;</span><br><span class="line"></span><br><span class="line">    obj2 = obj1; <span class="comment">// 使用赋值运算符重载进行赋值</span></span><br><span class="line"></span><br><span class="line">    std::cout &lt;&lt; obj1.<span class="built_in">getData</span>() &lt;&lt; std::endl; <span class="comment">// 输出：5</span></span><br><span class="line">    std::cout &lt;&lt; obj2.<span class="built_in">getData</span>() &lt;&lt; std::endl; <span class="comment">// 输出：5</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这个示例中，<code>MyClass</code>类包含一个动态分配的整型数据<code>data</code>。</p>
<p>在拷贝构造函数中，我们为<code>data</code>创建新的内存，并将其值设置为被复制对象的值。</p>
<p>在赋值运算符重载中，首先检查是否是自我赋值，然后执行深拷贝。先删除原有的<code>data</code>内存，并为其分配新的内存，然后将其值设置为被赋值对象的值。</p>
<p>通过这样的实现，可以确保在赋值过程中进行深拷贝，从而避免内存重复释放的问题。</p>
<h2 id="其他运算符重载的说明"><a href="#其他运算符重载的说明" class="headerlink" title="其他运算符重载的说明"></a>其他运算符重载的说明</h2><hr>
<p>以下是C++中常见的运算符及其简单说明和是否能重载：</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
<th>是否能重载（只标识不能重载的）</th>
</tr>
</thead>
<tbody><tr>
<td><code>+</code></td>
<td>加法运算符，用于执行两个操作数的相加操作。</td>
<td></td>
</tr>
<tr>
<td><code>-</code></td>
<td>减法运算符，用于执行两个操作数的相减操作。</td>
<td></td>
</tr>
<tr>
<td><code>*</code></td>
<td>乘法运算符，用于执行两个操作数的相乘操作。</td>
<td></td>
</tr>
<tr>
<td><code>/</code></td>
<td>除法运算符，用于执行两个操作数的相除操作。</td>
<td></td>
</tr>
<tr>
<td><code>%</code></td>
<td>取模运算符，返回两个操作数相除后的余数。</td>
<td></td>
</tr>
<tr>
<td><code>++</code></td>
<td>自增运算符，用于将操作数的值增加1。</td>
<td></td>
</tr>
<tr>
<td><code>--</code></td>
<td>自减运算符，用于将操作数的值减少1。</td>
<td></td>
</tr>
<tr>
<td><code>=</code></td>
<td>赋值运算符，用于将右侧操作数的值赋给左侧操作数。</td>
<td></td>
</tr>
<tr>
<td><code>+=</code></td>
<td>加法赋值运算符，将右侧操作数的值加到左侧操作数上。</td>
<td></td>
</tr>
<tr>
<td><code>-=</code></td>
<td>减法赋值运算符，将右侧操作数的值从左侧操作数中减去。</td>
<td></td>
</tr>
<tr>
<td><code>*=</code></td>
<td>乘法赋值运算符，将右侧操作数的值乘到左侧操作数上。</td>
<td></td>
</tr>
<tr>
<td><code>/=</code></td>
<td>除法赋值运算符，将左侧操作数除以右侧操作数的值。</td>
<td></td>
</tr>
<tr>
<td><code>%=</code></td>
<td>取模赋值运算符，将左侧操作数取模右侧操作数的值。</td>
<td></td>
</tr>
<tr>
<td><code>==</code></td>
<td>相等运算符，用于比较两个操作数是否相等。</td>
<td></td>
</tr>
<tr>
<td><code>!=</code></td>
<td>不等运算符，用于比较两个操作数是否不相等。</td>
<td></td>
</tr>
<tr>
<td><code>&gt;</code></td>
<td>大于运算符，用于比较左侧操作数是否大于右侧操作数。</td>
<td></td>
</tr>
<tr>
<td><code>&lt;</code></td>
<td>小于运算符，用于比较左侧操作数是否小于右侧操作数。</td>
<td></td>
</tr>
<tr>
<td><code>&gt;=</code></td>
<td>大于等于运算符，用于比较左侧操作数是否大于或等于右侧操作数。</td>
<td></td>
</tr>
<tr>
<td><code>&lt;=</code></td>
<td>小于等于运算符，用于比较左侧操作数是否小于或等于右侧操作数。</td>
<td></td>
</tr>
<tr>
<td><code>&amp;&amp;</code></td>
<td>逻辑与运算符，用于执行逻辑与操作。</td>
<td></td>
</tr>
<tr>
<td>&#96;</td>
<td></td>
<td>&#96;</td>
</tr>
<tr>
<td><code>!</code></td>
<td>逻辑非运算符，用于执行逻辑非操作。</td>
<td></td>
</tr>
<tr>
<td><code>&amp;</code></td>
<td>按位与运算符，对操作数的每个位执行逻辑与操作。</td>
<td></td>
</tr>
<tr>
<td>&#96;</td>
<td>&#96;</td>
<td>按位或运算符，对操作数的每个位执行逻辑或操作。</td>
</tr>
<tr>
<td><code>^</code></td>
<td>按位异或运算符，对操作数的每个位执行逻辑异或操作。</td>
<td></td>
</tr>
<tr>
<td><code>~</code></td>
<td>按位取反运算符，对操作数的每个位取反。</td>
<td></td>
</tr>
<tr>
<td><code>&lt;&lt;</code></td>
<td>左移运算符，将操作数的位向左移动指定的位数。</td>
<td></td>
</tr>
<tr>
<td><code>&gt;&gt;</code></td>
<td>右移运算符，将操作数的位向右移动指定的位数。</td>
<td></td>
</tr>
<tr>
<td><code>&amp;=</code></td>
<td>按位与赋值运算符，将右侧操作数的值与左侧操作数进行按位与操作。</td>
<td></td>
</tr>
<tr>
<td>&#96;</td>
<td>&#x3D;&#96;</td>
<td>按位或赋值运算符，将右侧操作数的值与左侧操作数进行按位或操作。</td>
</tr>
<tr>
<td><code>^=</code></td>
<td>按位异或赋值运算符，将右侧操作数的值与左侧操作数进行按位异或操作。</td>
<td></td>
</tr>
<tr>
<td><code>&lt;&lt;=</code></td>
<td>左移赋值运算符，将左侧操作数的值向左移动指定的位数。</td>
<td></td>
</tr>
<tr>
<td><code>&gt;&gt;=</code></td>
<td>右移赋值运算符，将左侧操作数的值向右移动指定的位数。</td>
<td></td>
</tr>
<tr>
<td><code>sizeof</code></td>
<td>大小运算符，用于返回一个对象或数据类型的大小（以字节为单位）。</td>
<td>否</td>
</tr>
<tr>
<td><code>?:</code></td>
<td>条件运算符（三目运算符），用于根据条件选择不同的值。</td>
<td>否</td>
</tr>
<tr>
<td><code>.</code></td>
<td>成员访问运算符，用于访问结构体或类的成员。</td>
<td>否</td>
</tr>
<tr>
<td><code>-&gt;</code></td>
<td>成员指针访问运算符，用于通过指针访问结构体或类的成员。</td>
<td></td>
</tr>
<tr>
<td><code>[]</code></td>
<td>下标运算符，用于访问数组或容器中的元素。</td>
<td></td>
</tr>
<tr>
<td><code>()</code></td>
<td>函数调用运算符，用于调用函数。</td>
<td></td>
</tr>
<tr>
<td><code>new</code></td>
<td>动态分配运算符，用于在堆上分配内存空间。</td>
<td></td>
</tr>
<tr>
<td><code>delete</code></td>
<td>动态释放运算符，用于释放动态分配的内存空间。</td>
<td></td>
</tr>
<tr>
<td><code>new[]</code></td>
<td>数组动态内存分配运算符，用于在堆上分配数组内存</td>
<td></td>
</tr>
<tr>
<td><code>delete[]</code></td>
<td>数组动态内存释放运算符，用于释放先前分配的数组内存</td>
<td></td>
</tr>
<tr>
<td><code>.*</code></td>
<td>成员指针运算符，用于通过指针访问类的成员函数或成员变量。</td>
<td>否</td>
</tr>
<tr>
<td><code>-&gt;*</code></td>
<td>成员指针运算符，用于通过指针访问类的成员函数或成员变量。</td>
<td></td>
</tr>
<tr>
<td><code>::</code></td>
<td>作用域解析运算符，用于访问命名空间、类、结构体或枚举的成员。</td>
<td>否</td>
</tr>
<tr>
<td><code>,</code></td>
<td>逗号运算符，用于在表达式中分隔多个表达式，并按顺序执行</td>
<td></td>
</tr>
</tbody></table>
<ul>
<li><p>上述列表列出了绝大部分常用的运算符，但不是所有运算符的完整列表。还有其他一些运算符它们使用相对较少，这里不列出。</p>
</li>
<li><p>对于其余一些简单的运算符如：比较运算符、逻辑运算符等，请以上面四篇运算符重载的示例作为参考。</p>
</li>
<li><p>剩下的一些功能较为复杂的运算符如：<code>new</code>、<code>delete</code>、<code>,</code>、<code>-&gt;*</code>等的重载属于进阶内容，视情况而定，这里不给出示例代码。</p>
</li>
</ul>
<h1 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h1><h2 id="继承方式"><a href="#继承方式" class="headerlink" title="继承方式"></a>继承方式</h2><hr>
<ul>
<li><p>继承方式分为三种：公共继承（public）、保护继承（protected）、私有继承（private）</p>
</li>
<li><p>所有继承方式均不可访问父类中的私有成员</p>
</li>
<li><p>公共继承父类的子类，其父类的成员的访问属性不变。即：公共继承，父类中的公共成员在子类中仍然是公共成员，父类中的保护成员在子类中仍然是保护成员</p>
</li>
<li><p>私有继承的子类中，除了父类中的私有成员，其余所有的成员在子类中都变为私有成员。</p>
</li>
</ul>
<h2 id="继承中的对象模型"><a href="#继承中的对象模型" class="headerlink" title="继承中的对象模型"></a>继承中的对象模型</h2><hr>
<p>父类中私有成员也是被子类继承下去了，只是由编译器给隐藏后访问不到。</p>
<p>在C++中，子类会继承父类的所有非静态成员，包括私有成员。但是，对于私有成员，编译器会隐藏它们，使其在子类中不可直接访问。这是通过访问权限控制来实现的。</p>
<p>子类继承了父类的私有成员，但无法直接访问这些私有成员。私有成员在子类中仍然存在，并占据相应的内存空间，但无法通过子类对象或指针直接访问。</p>
<p>子类可以通过继承的公有和保护成员来间接访问父类的私有成员。子类可以通过调用父类的公有和保护成员函数来操作父类的私有成员。这样，子类可以间接地使用继承下来的私有成员。</p>
<p>继承使子类拥有了父类的所有非静态成员，但私有成员被编译器隐藏起来，无法直接访问。子类通过父类的公有和保护成员来间接操作和使用继承的私有成员，从而达到了私有成员在子类中不可访问的效果。</p>
<p>私有成员的存在对于子类是有影响的。子类对象会继承父类的私有成员，这些私有成员在子类对象中占据内存空间。如果子类定义了与父类私有成员名称相同的成员，那么子类的成员是不会覆盖父类的私有成员的，父类私有成员仍然存在，仍然占据内存空间。</p>
<h2 id="继承中的构造和析构顺序"><a href="#继承中的构造和析构顺序" class="headerlink" title="继承中的构造和析构顺序"></a>继承中的构造和析构顺序</h2><hr>
<p>继承中先调用父类构造函数，再调用子类构造函数，析构顺序与构造相反。</p>
<p>先创建父类对象，再创建子类对象。</p>
<h2 id="同名成员处理"><a href="#同名成员处理" class="headerlink" title="同名成员处理"></a>同名成员处理</h2><hr>
<p>访问子类同名成员直接访问即可</p>
<p>访问父类同名成员需要加作用域</p>
<p>如果子类中出现和父类同名的成员函数，子类的同名成员会隐藏掉父类中所有同名成员函数</p>
<p>如果想访问到父类中被隐藏的同名成员函数，需要加作用域</p>
<p>静态成员和非静态成员出现同名，处理方式一致</p>
<ul>
<li><p>访问子类同名成员直接访问即可</p>
</li>
<li><p>访问父类同名成员需要加作用域</p>
</li>
</ul>
<p>静态成员变量：所有对象都共享同一份数据，编译阶段分配内存，类内声明，类外初始化</p>
<p>静态成员函数：只能访问静态成员变量</p>
<h2 id="多继承"><a href="#多继承" class="headerlink" title="多继承"></a>多继承</h2><hr>
<p>语法：</p>
<p> <code>class子类 : 继承方式 父类1, 继承方式 父类2 ...</code></p>
<p>多继承可能会引发父类中有同名成员出现，需要加作用域区分</p>
<p>语法示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">C</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">D</span> : <span class="keyword">public</span> A, <span class="keyword">protected</span> C, <span class="keyword">private</span> B </span><br><span class="line">&#123;&#125;;</span><br></pre></td></tr></table></figure></div>



<h2 id="菱形继承和虚继承"><a href="#菱形继承和虚继承" class="headerlink" title="菱形继承和虚继承"></a>菱形继承和虚继承</h2><hr>
<p>菱形继承带来的主要问题是子类继承两份相同的数据，导致资源浪费以及形同继承内容无意义</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src=""
                     
                ></p>
<p>为了解决多继承时的命名冲突和冗余数据问题，C++ 提出了虚继承，使得在派生类中只保留一份间接基类的成员。</p>
<p>在继承之前加上关键字<code>virtual</code>变为虚继承。</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src=""
                     
                ></p>
<p>语法示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> : <span class="keyword">virtual</span> <span class="keyword">public</span> A	<span class="comment">//B虚继承A</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">C</span> : <span class="keyword">virtual</span> <span class="keyword">public</span> A	<span class="comment">//C虚继承A</span></span><br><span class="line">&#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">D</span> : <span class="keyword">public</span> A, <span class="keyword">public</span> B</span><br><span class="line">&#123;&#125;;</span><br></pre></td></tr></table></figure></div>

<p>这样子，<code>D</code>类中就只有一份<code>A</code>类中的数据了。</p>
<p>视频讲解：<a class="link"   target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1et411b73Z?p=134&vd_source=03da7de0e80f9ff60fdeca7b512ba3f5" >【黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难】 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<h1 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h1><h2 id="多态的概念"><a href="#多态的概念" class="headerlink" title="多态的概念"></a>多态的概念</h2><hr>
<p>多态是C++面向对象三大特性之一。它意味着调用成员函数时，会根据调用函数的对象的类型来执行不同的函数。</p>
<p>在C++中，允许通过基类型的指针或引用去访问派生对象中的函数，并允许需要执行的函数在运行时进行延迟绑定 (Late binding)，这称之为多态。</p>
<p>多态的目的是为了&#x3D;&#x3D;接口重用&#x3D;&#x3D;。也即，不论传递过来的究竟是类的哪个对象，函数都能够通过同一个接口调用到适应各自对象的实现方法。这样可以提高代码的可扩展性和可维护性。</p>
<p>当类之间存在层次结构，并且类之间是通过继承关联时，就会用到多态。</p>
<p>C++ 多态意味着调用成员函数时，会根据调用函数的对象的类型来执行不同的函数。</p>
<p>多态分为两类</p>
<ul>
<li><p>静态多态：函数重载和运算符重载属于静态多态，复用函数名</p>
</li>
<li><p>动态多态：派生类和虚函数实现运行时多态</p>
</li>
</ul>
<p>静态多态和动态多态区别：</p>
<ul>
<li><p>静态多态的函数地址早绑定–编译阶段确定函数地址</p>
</li>
<li><p>动态多态的函数地址晚绑定–运行阶段确定函数地址</p>
</li>
</ul>
<h2 id="虚函数"><a href="#虚函数" class="headerlink" title="虚函数"></a>虚函数</h2><hr>
<p>虚函数是 C++ 中的一个重要概念，它允许基类指针能够在运行时动态地绑定到派生类对象的成员函数上。</p>
<p>简单来说，虚函数是一个在基类中声明的函数，在派生类中可以被重写。在运行时，如果使用基类指针调用虚函数，那么实际上会调用指向派生类对象的函数。</p>
<p>使用虚函数可以实现多态性，使得程序能够根据实际的对象类型来调用相应的成员函数，而不是在编译时就确定调用的函数。</p>
<p>在 C++ 中，将函数声明为虚函数的方法是在函数声明前加上关键字<code>virtual</code>。</p>
<p>派生类和虚函数实现运行时多态属于动态多态，动态多态的满足条件 ：</p>
<ul>
<li>有继承关系</li>
<li>子类重写父类的虚函数</li>
</ul>
<p>示例代码：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">animal</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">speak01</span><span class="params">()</span><span class="comment">//虚函数</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;动物在叫&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak02</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;动物在叫&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">dog</span> :<span class="keyword">public</span> animal</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak01</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;汪汪汪&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak02</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;汪汪汪&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">cat</span> : <span class="keyword">public</span> animal</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak01</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;喵喵喵&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak02</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;喵喵喵&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//执行说话的函数</span></span><br><span class="line"><span class="comment">//地址早绑定在编译阶段确定函数地址</span></span><br><span class="line"><span class="comment">//如果想执行让猫喵喵喵，那么这个函数地址就不能提前绑定，需要在运行阶段进行绑定，地址晚绑定</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">speak</span><span class="params">(animal&amp; animal)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	animal.<span class="built_in">speak01</span>();</span><br><span class="line">	animal.<span class="built_in">speak02</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	cat cat01;</span><br><span class="line">	dog dog01;</span><br><span class="line">	<span class="built_in">speak</span>(cat01);</span><br><span class="line">	<span class="built_in">speak</span>(dog01);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line"></span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="虚函数原理剖析"><a href="#虚函数原理剖析" class="headerlink" title="虚函数原理剖析"></a>虚函数原理剖析</h2><hr>
<p>普通函数（非静态成员函数），不属于类的对象上，下面这个类的大小为1（空类大小为1）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">animal</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">speak</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;动物在说话&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout&lt;&lt; <span class="built_in">sizeof</span>(animal) &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1</span><br></pre></td></tr></table></figure></div>

<p>当在非静态成员函数前加上<code>virtual</code>关键字后，原来的普通函数变成一个虚函数，这时候类的大小变为4。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">animal</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">   <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">speak</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;动物在说话&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cout&lt;&lt; <span class="built_in">sizeof</span>(animal) &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">4</span><br></pre></td></tr></table></figure></div>

<p>实际上，加上<code>virtual</code>关键字后，普通函数变成一个虚函数，虚函数实际上是一个指针，这个指针称为虚函数指针或虚函数表指针。因而类中多了一个指针类型的成员，大小发生了变化。</p>
<p>这个指针指向一个虚函数表，表的内部记录着这个类作用域下的对应的函数的地址。当子类继承后，子类成员中同样也有了一个虚函数指针，也指向一个虚函数表，如果没有重写这个虚函数，因为继承关系表中的内容与父类是完全一样的，表中的函数地址仍然是父类中对应的函数地址。当子类重写了这个虚函数，子类中的虚函数表内部会将原先父类中对应的函数地址替换成子类中重写的函数的函数地址。</p>
<p>当父类指针或引用指向子类对象时就发生了多态，当调用虚函数时，就发生了动态的多态，由于是子类对象调用，则从子对象的虚函数表中寻找子类重写后的函数。</p>
<h2 id="纯虚函数和抽象类"><a href="#纯虚函数和抽象类" class="headerlink" title="纯虚函数和抽象类"></a>纯虚函数和抽象类</h2><hr>
<p>在多态中，通常父类中虚函数的实现是毫无意义的，主要都是调用子类重写的内容</p>
<p>因此可以将虚函数改为纯虚函数</p>
<p>纯虚函数语法：<code>virtual返回值类型 函数名(参数列表) = 0 ;</code></p>
<p>当类中有了纯虚函数，这个类也称为抽象类。</p>
<p>抽象类特点:</p>
<ul>
<li><p>无法实例化对象</p>
</li>
<li><p>抽象类的子类必须要重写父类中的纯虚函数，否则也属于抽象类</p>
</li>
</ul>
<h2 id="虚析构和纯虚析构"><a href="#虚析构和纯虚析构" class="headerlink" title="虚析构和纯虚析构"></a>虚析构和纯虚析构</h2><hr>
<p>多态使用时，如果子类中有属性开辟到堆区，那么父类指针在释放时无法调用到子类的析构代码</p>
<p>解决方式:将父类中的析构函数改为虚析构或者纯虚析构</p>
<p>虚析构和纯虚析构共性：</p>
<ul>
<li><p>可以解决父类指针释放子类对象</p>
</li>
<li><p>都需要有具体的函数实现</p>
</li>
</ul>
<p>虚析构和纯虚析构区别：</p>
<ul>
<li><p>如果是纯虚析构，该类属于抽象类，无法实例化对象。</p>
</li>
<li><p>纯虚析构需要有函数定义。</p>
</li>
</ul>
<p>示例（父类指针指向子类对象，会导致子类无法析构）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">animal</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">animal</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;animal的构造函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	~<span class="built_in">animal</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;animal的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">speak01</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">cat</span> : <span class="keyword">public</span> animal</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">cat</span>(string name_)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;cat的构造函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">		name = <span class="keyword">new</span> <span class="built_in">string</span>(name_);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	~<span class="built_in">cat</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;cat的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (name != <span class="literal">nullptr</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;cat成员的内存释放&quot;</span> &lt;&lt; endl;</span><br><span class="line">			<span class="keyword">delete</span> name;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak01</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;喵喵喵&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	string* name = <span class="literal">nullptr</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	animal* ani = <span class="keyword">new</span> <span class="built_in">cat</span>(<span class="string">&quot;tom&quot;</span>);</span><br><span class="line">	ani-&gt;<span class="built_in">speak01</span>();</span><br><span class="line">	<span class="keyword">delete</span> ani;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line"></span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">animal的构造函数</span><br><span class="line">cat的构造函数</span><br><span class="line">喵喵喵</span><br><span class="line">animal的析构函数</span><br></pre></td></tr></table></figure></div>

<p>解决方法：将父类对的析构函数改成虚函数（虚析构）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">animal</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">animal</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;animal的构造函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">virtual</span> ~<span class="built_in">animal</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;animal的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">speak01</span><span class="params">()</span> </span>= <span class="number">0</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">cat</span> : <span class="keyword">public</span> animal</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">cat</span>(string name_)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;cat的构造函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">		name = <span class="keyword">new</span> <span class="built_in">string</span>(name_);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	~<span class="built_in">cat</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;cat的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (name != <span class="literal">nullptr</span>)</span><br><span class="line">		&#123;</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;cat成员的内存释放&quot;</span> &lt;&lt; endl;</span><br><span class="line">			<span class="keyword">delete</span> name;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">speak01</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;喵喵喵&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	string* name = <span class="literal">nullptr</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	animal* ani = <span class="keyword">new</span> <span class="built_in">cat</span>(<span class="string">&quot;tom&quot;</span>);</span><br><span class="line">	ani-&gt;<span class="built_in">speak01</span>();</span><br><span class="line">	<span class="keyword">delete</span> ani;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line"></span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">animal的构造函数</span><br><span class="line">cat的构造函数</span><br><span class="line">喵喵喵</span><br><span class="line">cat的析构函数</span><br><span class="line">cat成员的内存释放</span><br><span class="line">animal的析构函数</span><br></pre></td></tr></table></figure></div>

<p>如果父类的析构函数是纯虚函数（纯虚析构），则必须要有函数体的实现（定义），需要在类外定义，否则运行报错（链接阶段找不到定义）。</p>
<h2 id="override关键字"><a href="#override关键字" class="headerlink" title="override关键字"></a><code>override</code>关键字</h2><hr>
<p><code>override</code>是C++11中引入的一个新关键字，用于显式地指定某个成员函数为虚函数的重写版本。当你在派生类中重写基类的虚函数时，可以在该函数的声明后面加上<code>override</code>关键字，表示该函数是重写基类的虚函数。</p>
<p>使用<code>override</code>关键字有两个好处：</p>
<ul>
<li><p>它能够帮助你避免一些常见的错误。例如，如果你在派生类中重写基类的虚函数时，不小心将函数名或参数列表写错了，编译器会报错，提示你这不是一个有效的重写。</p>
</li>
<li><p>它能够提高代码的可读性。当其他人阅读你的代码时，看到<code>override</code>关键字，就能够立即知道这是一个重写基类虚函数的函数。</p>
</li>
</ul>
<p>下面是一个简单的例子，演示如何使用<code>override</code>关键字：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Base</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">foo</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Base::foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Derived</span> : <span class="keyword">public</span> Base </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">()</span> <span class="keyword">override</span> </span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Derived::foo()&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Base* b = <span class="keyword">new</span> <span class="built_in">Derived</span>();</span><br><span class="line">    b-&gt;<span class="built_in">foo</span>(); <span class="comment">// 输出 &quot;Derived::foo()&quot;</span></span><br><span class="line">    <span class="keyword">delete</span> b;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在上面的例子中，我们在派生类<code>Derived</code>中重写了基类<code>Base</code>的虚函数<code>foo()</code>。在重写该函数时，我们在函数声明后面加上了<code>override</code>关键字，表示这是一个重写基类虚函数的函数。</p>
<h1 id="异常处理"><a href="#异常处理" class="headerlink" title="异常处理"></a>异常处理</h1><p>传统异常处理：</p>
<p>通过返回不同的值来体现或处理异常</p>
<p>缺点：</p>
<ul>
<li><p>返回值意义不明确</p>
</li>
<li><p>返回值返回一个消息</p>
</li>
<li><p>返回值可以忽略</p>
</li>
</ul>
<h2 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h2><hr>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">auto</span> <span class="title">fun</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (b == <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="comment">//throw &quot;被除数为0&quot;;</span></span><br><span class="line">		<span class="keyword">throw</span> <span class="number">0</span>;<span class="comment">//throw语句抛出异常,抛出异常为int类型 0</span></span><br><span class="line">		<span class="comment">//抛出异常后，直接执行catch里的代码，这里的后续代码不会执行</span></span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> (a / b);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">try</span><span class="comment">//将可能出现异常的语句放在try语句中</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; a &lt;&lt; <span class="string">&quot;除以&quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;等于&quot;</span> &lt;&lt; <span class="built_in">fun</span>(a, b) &lt;&lt; endl;;</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="comment">//一个try语句可以与多个catch相匹配，但至少需要有一个catch,catch用于接收异常，可以指定接收的类型</span></span><br><span class="line">	<span class="built_in">catch</span> (<span class="type">const</span> <span class="type">char</span>* a)<span class="comment">//接收到一个const char* 类型的异常</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; a&lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">catch</span> (<span class="type">int</span> a)<span class="comment">//接收到int 类型的异常</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">switch</span> (a)<span class="comment">//使用switch语句判断异常并处理</span></span><br><span class="line">		&#123;</span><br><span class="line">		<span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">			cout &lt;&lt; <span class="string">&quot;被除数等于0&quot;</span> &lt;&lt; endl;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">		<span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">			<span class="comment">//......</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="comment">//case .....</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="built_in">catch</span>(...)<span class="comment">//接收除了上面int和const char*以外的其他所有类型异常，如果只有这个就表示接收所有类型异常</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test</span>(<span class="number">10</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p><code>throw</code>还可以抛出自定义数据类型，从而可以调用抛出对象的成员函数进一步处理。</p>
<p><code>try</code>中的语句如果抛出异常，则必须进行处理，即：必须有对应的<code>catch</code>代码段进行接收。</p>
<p><code>try</code>中的语句如果没有抛出异常，则后续对应的所有<code>catch</code>代码段都不会执行。</p>
<h2 id="异常（接口）声明"><a href="#异常（接口）声明" class="headerlink" title="异常（接口）声明"></a>异常（接口）声明</h2><hr>
<p>该语法特性已在C++11后弃用，VS编译器中可以使用，无语法错误，但实际没有任何效果，同时也不建议使用该语法。这里不做介绍。</p>
<h2 id="noexcept关键字"><a href="#noexcept关键字" class="headerlink" title="noexcept关键字"></a><code>noexcept</code>关键字</h2><hr>
<p><code>noexcept</code>用于指定函数是不会抛出异常的。这个关键字对于异常处理和代码优化非常有用。</p>
<p>异常接口声明的语法在C++11被移除，在未被移除之前，声明一个不会抛出异常的函数是这样的：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">()</span> <span class="title">throw</span><span class="params">()</span><span class="comment">//表示这个函数不会抛出异常</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>该语法在C++11被移除，C++11后声明一个不会抛出异常的函数就要使用<code>noexcept</code>关键字</p>
<p>示例：</p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个会抛出异常的函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">mightThrow</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="string">&quot;This function might throw an exception.&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明一个不会引发异常的函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">noThrow</span><span class="params">()</span> <span class="keyword">noexcept</span> <span class="comment">//noexcept表示函数不会抛出异常</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;This function will not throw any exception.&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>如果在有<code>noexcept</code>修饰的函数中抛出了异常，并且在调用时接收了异常程序则会出现断点报错。</p>
<h2 id="异常对象的生命周期和栈解旋"><a href="#异常对象的生命周期和栈解旋" class="headerlink" title="异常对象的生命周期和栈解旋"></a>异常对象的生命周期和栈解旋</h2><hr>
<p>异常被抛出后，从进入<code>try</code>块起，到异常被抛掷前，这期间在栈上构造的所有对象，都会被自动析构。</p>
<p>析构的顺序与构造的顺序相反，这一过程称为栈的解旋（栈解旋）</p>
<p>示例1（过程中会创建3个对象）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">myclass</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的默认构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">myclass</span>(<span class="type">const</span> myclass&amp; other)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的拷贝构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	myclass one;	<span class="comment">//对象一	默认构造</span></span><br><span class="line">	<span class="keyword">throw</span> one;		<span class="comment">//对象二	拷贝构造</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">try</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">func</span>();</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="comment">//对象一	在catch接收之前析构</span></span><br><span class="line">	<span class="built_in">catch</span> (myclass erro)<span class="comment">//对象三	由对象二拷贝构造</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;接收到myclass类型异常&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="comment">//对象二和对象三在catch段处理完异常后就析构</span></span><br><span class="line">    	cout &lt;&lt; <span class="string">&quot;接收异常后&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">myclass的默认构造</span><br><span class="line">myclass的拷贝构造</span><br><span class="line">myclass的拷贝构造</span><br><span class="line">myclass的析构函数</span><br><span class="line">接收到myclass类型异常</span><br><span class="line">myclass的析构函数</span><br><span class="line">myclass的析构函数</span><br><span class="line">接收异常后</span><br></pre></td></tr></table></figure></div>

<p>示例2（过程中会创建两个对象）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">myclass</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的默认构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">myclass</span>(<span class="type">const</span> myclass&amp; other)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的拷贝构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">throw</span> <span class="built_in">myclass</span>();<span class="comment">//抛出匿名对象，避免拷贝，默认构造</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">try</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">func</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">catch</span> (myclass erro)<span class="comment">//拷贝构造，由匿名对象拷贝</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;接收到myclass类型异常&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">    <span class="comment">//匿名对象和erro析构</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;接收异常后&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">myclass的默认构造</span><br><span class="line">myclass的拷贝构造</span><br><span class="line">接收到myclass类型异常</span><br><span class="line">myclass的析构函数</span><br><span class="line">myclass的析构函数</span><br><span class="line">接收异常后</span><br></pre></td></tr></table></figure></div>

<p>示例3（过程中会创建一个对象）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">myclass</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的默认构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">myclass</span>(<span class="type">const</span> myclass&amp; other)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的拷贝构造&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	~<span class="built_in">myclass</span>()</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;myclass的析构函数&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">throw</span> <span class="built_in">myclass</span>();<span class="comment">//抛出匿名对象</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">try</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">func</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">catch</span> (myclass&amp; erro)<span class="comment">//引用接收throw抛出的匿名对象</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;接收到myclass类型异常&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;接收异常后&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">myclass的默认构造</span><br><span class="line">接收到myclass类型异常</span><br><span class="line">myclass的析构函数</span><br><span class="line">接收异常后</span><br></pre></td></tr></table></figure></div>

<p>总结：</p>
<p><code>throw</code>抛出的异常对象在<code>catch</code>处理完后才会被释放，使用<code>throw</code>抛出匿名对象可以在整个异常处理过程中只产生一个对象，避免拷贝构造。</p>
<p>抛出的堆区开辟的对象需要在<code>catch</code>中手动释放。</p>
<h2 id="异常中的多态"><a href="#异常中的多态" class="headerlink" title="异常中的多态"></a>异常中的多态</h2><hr>
<p>在<code>catch</code>中使用父类的引用接受子类对象，就会发生多态。当父类中有虚函数，并且子类重写后，那么<code>catch</code>中调用父类成员函数时就会调用子类中重写的函数。</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">father</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">error</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">son01</span> : <span class="keyword">public</span> father</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">error</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;son01异常&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">son02</span> : <span class="keyword">public</span> father</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">error</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;son02异常&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">func01</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (a == <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">throw</span> <span class="built_in">son01</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">if</span> (b == <span class="number">0</span>)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">throw</span> <span class="built_in">son02</span>();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">try</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">func01</span>(<span class="number">0</span>, <span class="number">10</span>);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">catch</span> (father&amp; fa)</span><br><span class="line">	&#123;</span><br><span class="line">		fa.<span class="built_in">error</span>();</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">try</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">func01</span>(<span class="number">10</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">catch</span>(father&amp; fa)</span><br><span class="line">	&#123;</span><br><span class="line">		fa.<span class="built_in">error</span>();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">son01异常</span><br><span class="line">son02异常</span><br></pre></td></tr></table></figure></div>

<h2 id="标准异常类std-exception"><a href="#标准异常类std-exception" class="headerlink" title="标准异常类std::exception"></a>标准异常类<code>std::exception</code></h2><hr>
<p>提供一致的接口，以通过<code>throw</code>表达式处理错误。</p>
<p>标准库所生成的所有异常继承自 <code>std::exception</code></p>
<p>继承关系（C++11前）：</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src=""
                     
                ></p>
<p>部分异常类描述：</p>
<table>
<thead>
<tr>
<th>异常类</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><strong><code>std::exception</code></strong></td>
<td><strong>该异常是所有标准 C++ 异常的父类。</strong></td>
</tr>
<tr>
<td><code>std::bad_alloc</code></td>
<td>用<code>new</code>动态分配空间失败</td>
</tr>
<tr>
<td><code>std::bad_cast</code></td>
<td>执行<code>dynamic_cast</code>失败</td>
</tr>
<tr>
<td><code>std::bad_typeid</code></td>
<td>对某个空指针<code>p</code>执行<code>typeid(*p) </code></td>
</tr>
<tr>
<td><code>std::bad_exception</code></td>
<td>当某个函数<code>fun()</code>因在执行过程中抛出了异常声明所不允许的异常而调用<code>unexpected()</code>函数时，若<code>unexpected()</code>函数又一次抛出了<code>fun()</code>的异常声明所不允许的异常，且<code>fun()</code>的异常声明列表中有<code>bad_exception</code>,则会有一个<code>bad_exception</code>异常在<code>fun()</code>的调用点被抛出</td>
</tr>
<tr>
<td><strong><code>std::logic_error</code></strong></td>
<td><strong>理论上可以通过读取代码来检测到的异常。</strong></td>
</tr>
<tr>
<td><code>std::domain_error</code></td>
<td>执行一段程序所需要的先决条件不满足</td>
</tr>
<tr>
<td><code>std::invalid_argument</code></td>
<td>表示向函数传入无效参数</td>
</tr>
<tr>
<td><code>std::length_error</code></td>
<td>尝试创建一个长度超过最大允许值的对象</td>
</tr>
<tr>
<td><code>std::out_of_range</code></td>
<td>表示一个参数值不在允许的范围之内</td>
</tr>
<tr>
<td><code>std::future_error</code></td>
<td>(C++11起) 它为处理异步执行和共享状态（<code>std::future</code>、<code>std::promise</code>等）的线程库中的函数在失败时抛出。同 <code>std::system_error</code> ，此异常携带与<code>std::error_code</code>兼容的错误码。</td>
</tr>
<tr>
<td><code>std::bad_optional_access</code></td>
<td>(C++17起) 定义 <code>std::optional::value</code>在访问不含值的 <code>optional</code> 对象时所抛出的异常对象类型。</td>
</tr>
<tr>
<td><strong><code>std::runtime_error</code></strong></td>
<td><strong>理论上不可以通过读取代码来检测到的异常</strong></td>
</tr>
<tr>
<td><code>std::overflow_error</code></td>
<td>算术运算时向上溢出</td>
</tr>
<tr>
<td><code>std::range error</code></td>
<td>内部计算时发生作用域的错误</td>
</tr>
<tr>
<td><code>std::underflow_error</code></td>
<td>算术运算时向下溢出</td>
</tr>
<tr>
<td><code>std::regex_error</code></td>
<td>(C++11起) 定义抛出的异常对象类型，以报告正则表达式库中的错误。</td>
</tr>
<tr>
<td><strong><code>std::system_error</code></strong></td>
<td>(C++11起) <code>std::system_error</code> 是多种库函数（通常是与 OS 设施交接的函数，例如 <code>std::thread</code>的构造函数）在拥有关联于该异常的 <code>std::error_code</code>时抛出的异常类型，同时可能报告该<code>std::error_code </code>。</td>
</tr>
<tr>
<td><code>std::ios_base::failure</code></td>
<td>用来表示C++的输入输出流执行过程中发生的错误。（C++17起，继承自<code>std::system_error</code>）</td>
</tr>
<tr>
<td><code>std::filesystem::filesystem_error</code></td>
<td>(C++17起)类 <code>std::filesystem::filesystem_error</code> 定义文件系统库中函数的抛出版重载所抛出的异常对象。</td>
</tr>
</tbody></table>
<p>加粗的表示下方是其子类。</p>
<p>说明：还有相当多的异常类这里未全部列出，大都是C++11及C++11后的新标准定义的，这里不做再做说明，详细请查阅手册有关：标准库标头<code>&lt;exception&gt;</code>部分，上述表格已经能满足绝大部分使用场景。</p>
<h2 id="标准异常类的使用示例"><a href="#标准异常类的使用示例" class="headerlink" title="标准异常类的使用示例"></a>标准异常类的使用示例</h2><hr>
<p>一些C++语法或某些功能在使用时也许会发生错误，这些语法或功能在其内部实现时，也许就会将这些错误作为异常抛出，</p>
<p>这些异常都属于标准异常<code>std::exception</code>或其子类，都可以用<code>std::exception</code>的引用来接收，从而处理异常。</p>
<p>详细见视频（讲解的很好）：<a class="link"   target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV16T41167Zr?vd_source=03da7de0e80f9ff60fdeca7b512ba3f5" >【C++教程 第十三章（2）异常Exception深入解剖】 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;exception&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span> </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="function">vector&lt;<span class="type">int</span>&gt; <span class="title">a</span><span class="params">(<span class="number">9999999999999999999</span>)</span></span>;<span class="comment">//指定vector容器一个很大很大的空间，在vector内部代码中这将会作为一个错误异常抛出</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">catch</span> (exception&amp; erro)<span class="comment">//抛出的类都是exception类或其子类，使用父类引用接收（多态）</span></span><br><span class="line">    &#123;</span><br><span class="line">        cerr &lt;&lt; erro.<span class="built_in">what</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出结果：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vector too long</span><br></pre></td></tr></table></figure></div>

<h2 id="自定义异常类继承标准异常类"><a href="#自定义异常类继承标准异常类" class="headerlink" title="自定义异常类继承标准异常类"></a>自定义异常类继承标准异常类</h2><hr>
<p>可以通过继承和重载 <code>exception</code>类或其他标准异常类来定义新的异常。</p>
<p>下面的实例演示了如何使用<code>std::exception</code>类来实现自己的异常：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;exception&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyException</span> : <span class="keyword">public</span> exception </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">MyException</span>(<span class="type">const</span> string&amp; message) : <span class="built_in">message_</span>(message) &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="type">const</span> <span class="type">char</span>* <span class="title">what</span><span class="params">()</span> <span class="type">const</span> <span class="comment">/*noexcept*/</span> <span class="keyword">override</span><span class="comment">//noexcept属于异常（接口）声明，C++11后无任何效果，可忽略</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> message_.<span class="built_in">c_str</span>();</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    std::string message_;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span> </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="built_in">MyException</span>(<span class="string">&quot;!!!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">catch</span> (exception&amp; erro)</span><br><span class="line">    &#123;</span><br><span class="line">        cerr &lt;&lt; erro.<span class="built_in">what</span>() &lt;&lt; <span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这里，<code>what()</code> 是父异常类<code>std::exception</code>提供的一个公共方法，是一个虚函数，它已被所有子异常类重写，同样在自定义异常类中也需要重写，这也体现了C++多态的特性。</p>
<p>输出结果：</p>
<div class="highlight-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">!!!</span><br></pre></td></tr></table></figure></div>

<h1 id="模板基础"><a href="#模板基础" class="headerlink" title="模板基础"></a>模板基础</h1><h2 id="模板和泛型编程的概念"><a href="#模板和泛型编程的概念" class="headerlink" title="模板和泛型编程的概念"></a>模板和泛型编程的概念</h2><hr>
<p>泛型编程是一种编程模式，它核心的思想是增加代码的通用性和复用性，使代码能够适用于多种不同的数据类型。</p>
<p>传统的程序设计中，通常会写出多个函数或类来处理不同类型的数据。例如，在C语言中，为了实现针对不同类型的数组排序算法，需要为每一种数据类型编写相应的排序函数，这样会导致代码的冗余和重复。而泛型编程则可以使用单一的函数或类来实现通用的数据操作，避免了这种冗余和重复。</p>
<p>通过使用泛型编程，我们能够实现针对各种类型的数据，使用相同的代码进行处理。这种方式可以带来更高的代码复用性和可维护性，并可以避免出现多个函数或类的代码冗余的情况。</p>
<p>C++语言中的模板就是泛型编程的一种主要实现方式。使用C++模板，我们可以很方便地编写通用的函数或类来处理任意数据类型，极大地提高了代码的复用性、可维护性和可读性。</p>
<p>模板是C++中的一种高级编程特性，简单来说，模板就是一种让程序员编写具有参数类型或参数化表达式的函数和类的机制。利用模板，程序员可以充分利用C++的类型安全和可重用性。</p>
<p>C++中的模板可以分为函数模板和类模板两种。函数模板是将函数定义为泛型的，允许在不同数据类型下共享算法的代码。类模板则是将类定义为泛型的，允许在不同数据类型下共享类的代码实现。</p>
<p>模板的主要用途可以总结为以下几点：</p>
<ol>
<li><p>泛型编程：可以使用模板实现通用算法，可以很方便地处理不同类型的数据。</p>
</li>
<li><p>可重用性：可以通过实例化不同类型的模板，实现数值计算、数据结构等算法的一般化处理，从而大大提高代码的可重用性。</p>
</li>
<li><p>类型安全：使用模板的好处在于可以发现编译器在编译期间能够发现类型错误，从而提高程序的错误检测和安全性。</p>
</li>
</ol>
<p>总之，模板是一种非常重要的C++编程特性，它可以使程序员高效地实现通用算法和数据结构，提高程序的可读性、可重用性和安全性。</p>
<h2 id="函数模板"><a href="#函数模板" class="headerlink" title="函数模板"></a>函数模板</h2><hr>
<h3 id="语法规则"><a href="#语法规则" class="headerlink" title="语法规则"></a>语法规则</h3><hr>
<p>函数模板是一种用于生成通用代码的功能。模板参数允许将函数的参数和返回类型作为模板的参数进行定义，这样可以将同样的代码用于不同的数据类型，从而减少代码冗余和提高代码的重用性。</p>
<p>函数模板的语法形式如下：</p>
<p>语法：“<code>template关键字</code>” + “<code>&lt;typename T&gt;</code>” 或 “<code>&lt;class T&gt;</code>” ，其中<code>T</code>是可自定义的名称，一般用大写字母，对于函数模板来说，<code>typename </code>和<code>class</code>没有区别。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;<span class="comment">//声明接下来将要写一个函数模板</span></span><br><span class="line"><span class="comment">//接下来的一个函数，将作为函数模板</span></span><br><span class="line"><span class="comment">//示例：</span></span><br><span class="line"><span class="function">T <span class="title">max</span><span class="params">(T x, T y)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">return</span> (x &gt; y) ? x : y;<span class="comment">//返回较大者</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>对于上面的例子，使用函数模板时，可以在调用函数时将数据类型作为实参传递给模板参数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">5</span>, b = <span class="number">10</span>;</span><br><span class="line"><span class="type">double</span> c = <span class="number">3.14</span>, d = <span class="number">2.718</span>;</span><br><span class="line"><span class="type">int</span> max_int = <span class="built_in">max</span>&lt;<span class="type">int</span>&gt;(a, b);</span><br><span class="line"><span class="type">double</span> max_double = <span class="built_in">max</span>&lt;<span class="type">double</span>&gt;(c, d);</span><br></pre></td></tr></table></figure></div>

<p>在调用<code>max</code>函数时，使用了尖括号<code>&lt;&gt;</code>将数据类型作为实参传递给模板参数<code>T</code>，从而实例化了一个特定类型的函数。</p>
<p>在第一次调用<code>max</code>时，<code>T</code>被指定为<code>int</code>类型，在第二次调用<code>max</code>时，<code>T</code>被指定为<code>double</code>类型。这样就可以在不同的数据类型之间进行比较操作，从而提高代码的重用性和可读性。</p>
<p>同样的，也可以不指定<code>T</code>的类型，不指定类型时，将由编译器自动根据传入参数推导<code>T</code>的类型。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">5</span>, b = <span class="number">10</span>;</span><br><span class="line"><span class="type">double</span> c = <span class="number">3.14</span>, d = <span class="number">2.718</span>;</span><br><span class="line"><span class="type">int</span> max_int = <span class="built_in">max</span>(a, b);</span><br><span class="line"><span class="type">double</span> max_double = <span class="built_in">max</span>(c, d);</span><br></pre></td></tr></table></figure></div>

<p>在以上示例中，我们没有显式地指定<code>T</code>类型，而是将不同类型的变量<code>a</code>和<code>b</code>、<code>c</code>和<code>d</code>传递给了<code>max</code>函数。编译器可以推导出<code>a</code>和<code>b</code>的类型是<code>int</code>，而<code>c</code>和<code>d</code>的类型是<code>double</code>，因此编译器会自动实例化一个<code>max</code>函数模板，用于比较<code>int</code>和<code>double</code>类型的数据并返回较大值。</p>
<p>&#x3D;&#x3D;注意事项：&#x3D;&#x3D;<code>T</code>的类型必须一致，否则会报错。</p>
<p>如下所示：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">auto</span> result = <span class="built_in">max</span>(<span class="number">1</span>, <span class="number">2.5</span>);</span><br></pre></td></tr></table></figure></div>

<p>由于<code>1</code>和<code>2.5</code>的类型不同，编译器进行类型推导时，<code>T</code>的类型不一致，因此会报错。</p>
<p>建议在参数类型明确时，显示指定<code>T</code>的类型。</p>
<h3 id="普通函数和函数模板的调用规则"><a href="#普通函数和函数模板的调用规则" class="headerlink" title="普通函数和函数模板的调用规则"></a>普通函数和函数模板的调用规则</h3><hr>
<p>函数模板和普通函数可以发生重载，函数模板间也可以发生重载，当普通函数和模板函数发生重载时，对于传入的参数如果都满足，在没有显示指定模板参数类型的情况下会优先调用普通函数。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;foo(int) called with x = &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(T x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;foo(T) called with x = &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">foo</span>(<span class="number">123</span>); <span class="comment">// 调用普通函数</span></span><br><span class="line">    <span class="built_in">foo</span>(<span class="number">3.14</span>); <span class="comment">// 调用函数模板</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在此示例中，我们定义了一个名为<code>foo</code>的普通函数和一个同名的函数模板。当我们在<code>main</code>函数中调用<code>foo</code>函数时，编译器会优先选择普通函数而不是函数模板，因为普通函数的匹配级别更高。</p>
<p>通过显示指定模板参数类型或指定模板参数类型为空，可以强制调用函数模板。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="Cpp"><figure class="iseeu highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> x = <span class="number">123</span>;</span><br><span class="line"><span class="built_in">foo</span>(x); <span class="comment">// 调用普通函数</span></span><br><span class="line"><span class="built_in">foo</span>&lt;<span class="type">int</span>&gt;(x); <span class="comment">// 调用函数模板</span></span><br><span class="line">foo&lt;&gt;(x); <span class="comment">// 调用函数模板</span></span><br></pre></td></tr></table></figure></div>

<p>如果函数模板可以对参数产生更好的匹配，则优先调用函数模板。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;foo(int) called with x = &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">foo</span><span class="params">(T x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;foo(T) called with x = &quot;</span> &lt;&lt; x &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">char</span> c = <span class="string">&#x27;c&#x27;</span>;</span><br><span class="line">    <span class="built_in">foo</span>(c); <span class="comment">// 调用函数模板</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>上述例子中调用普通函数时，需要进行隐式类型转换，而调用函数模板时不需要，则编译器优先调用函数模板。</p>
<p>&#x3D;&#x3D;！&#x3D;&#x3D;在实际开发中，不建议普通函数和函数模板重载，容易引起二义性。&#x3D;&#x3D;！&#x3D;&#x3D;</p>
<h3 id="普通函数和函数模板的区别"><a href="#普通函数和函数模板的区别" class="headerlink" title="普通函数和函数模板的区别"></a>普通函数和函数模板的区别</h3><hr>
<p>普通函数可以自动进行隐式类型转换，而函数模板在不显示指定模板参数类型的情况下，不能进行隐式转换。只有在显示指定模板参数类型的情况下才能自动进行隐式类型转换。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">add01</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span></span><br><span class="line"><span class="function">T <span class="title">add02</span><span class="params">(T a, T b)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>当我们调用普通函数<code>max</code>时，如果传入的参数不是<code>int</code>类型，系统会通过隐式类型转换将其转换为<code>int</code>类型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">3</span>;</span><br><span class="line"><span class="type">char</span> b = <span class="string">&#x27;c&#x27;</span>;</span><br><span class="line"><span class="type">int</span> c = <span class="built_in">add01</span>(a, b); <span class="comment">// 系统会自动将 char 类型的 b ，转换成对应的 int 类型的 ASCII码 </span></span><br></pre></td></tr></table></figure></div>

<p>而对于函数模板<code>add02</code>，如果传入的参数不是同一类型，在不显示指定模板参数类型时，会报错：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">3</span>;</span><br><span class="line"><span class="type">char</span> b = <span class="string">&#x27;c&#x27;</span>;</span><br><span class="line"><span class="comment">//int c = add02(a, b); // 编译器报错</span></span><br></pre></td></tr></table></figure></div>

<p>当显示指定模板参数类型时，编译器则会自动进行隐式类型转换：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">3</span>;</span><br><span class="line"><span class="type">char</span> b = <span class="string">&#x27;c&#x27;</span>;</span><br><span class="line"><span class="type">int</span> c = <span class="built_in">add02</span>&lt;<span class="type">int</span>&gt;(a, b); <span class="comment">// 会进行隐式类型转换，将 b 转成对应的 ASCII码</span></span><br></pre></td></tr></table></figure></div>



<p>&#x3D;&#x3D;补充说明：&#x3D;&#x3D;调用函数模板时，不显示指定模板类型的调用方式，称之为自动类型推导，所以调用函数模板由两种方式：自动类型推导和显示指定模板参数类型</p>
<h2 id="类模板"><a href="#类模板" class="headerlink" title="类模板"></a>类模板</h2><hr>
<h3 id="语法规则-1"><a href="#语法规则-1" class="headerlink" title="语法规则"></a>语法规则</h3><hr>
<p>类模板允许用户创建一种通用的类，使得类中的某些数据成员或成员函数的参数、返回值可以取任意类型。</p>
<p>语法：“<code>template关键字</code>” + “<code>&lt;class T1,class T2,...&gt;</code>” ，其中<code>T</code>是可自定义的名称，一般用大写字母，”<code>...</code>“表示可以有多个自定义的模板参数。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>,...&gt;   </span><br><span class="line"><span class="keyword">class</span> <span class="title class_">class_name</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//成员变量、函数</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p>类模板示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_name = name;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_age = age;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T1 _name;</span><br><span class="line">	T2 _age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">Person&lt;string, <span class="type">int</span>&gt; <span class="title">p1</span><span class="params">(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>)</span></span>;<span class="comment">//指定成员的类型为string和int</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; p1._name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; p1._age &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出结果：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">姓名：张三  年龄：<span class="number">20</span></span><br></pre></td></tr></table></figure></div>

<h3 id="类模板和函数模板的区别"><a href="#类模板和函数模板的区别" class="headerlink" title="类模板和函数模板的区别"></a>类模板和函数模板的区别</h3><hr>
<ul>
<li><p>类模板没有自动类型推导的使用方式</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_name = name;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_age = age;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T1 _name;</span><br><span class="line">	T2 _age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">Person&lt;string, <span class="type">int</span>&gt; <span class="title">p1</span><span class="params">(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>)</span></span>;<span class="comment">//指定模板参数类型为string和int</span></span><br><span class="line">    <span class="comment">//Person p1(&quot;张三&quot;, 20);//错误，类模板无法使用自动类型推导</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; p1._name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; p1._age &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>类模板在模板参数列表中可以有默认参数</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span> = <span class="type">int</span>&gt;<span class="comment">//指定T2有默认的类型为int</span></span><br><span class="line"><span class="keyword">class</span> Person</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_name = name;</span><br><span class="line">		<span class="keyword">this</span>-&gt;_age = age;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T1 _name;</span><br><span class="line">	T2 _age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">Person&lt;string&gt; <span class="title">p1</span><span class="params">(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>)</span></span>;<span class="comment">//指定第一个模板参数类型为string，第二个可以不指定，因为模板参数中第二个有默认参数int</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; p1._name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; p1._age &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h3 id="类模板中成员函数的创建时机"><a href="#类模板中成员函数的创建时机" class="headerlink" title="类模板中成员函数的创建时机"></a>类模板中成员函数的创建时机</h3><hr>
<p>类模板中成员函数和普通类中成员函数创建时机是有区别的：</p>
<ul>
<li>普通类中的成员函数—开始就可以创建</li>
<li>类模板中的成员函数在调用时才创建</li>
</ul>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass1</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">fun1</span><span class="params">()</span> </span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;MyClass1的fun1的调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass2</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">fun2</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;MyClass2的fun2的调用&quot;</span> &lt;&lt; endl;</span><br><span class="line">	&#125;;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    T1 obj;</span><br><span class="line">    </span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">fun1</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		obj.<span class="built_in">fun1</span>();<span class="comment">//编译不会报错，但调用时如果T1不是MyClass1类型就会报错</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">fun2</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		obj.<span class="built_in">fun2</span>();<span class="comment">//编译不会报错，但调用时如果T1不是MyClass2类型就会报错</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//上述两个注释说明，类模板的成员函数是在调用时才创建的</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="comment">//Person&lt;int&gt; p1;//错误</span></span><br><span class="line">	<span class="comment">//p1.fun1();</span></span><br><span class="line">    </span><br><span class="line">    Person&lt;MyClass1&gt; p1;</span><br><span class="line">	p1.<span class="built_in">fun1</span>();<span class="comment">//显示：MyClass1的fun1的调用</span></span><br><span class="line">	<span class="comment">//p1.fun2();错误，MyClass1没有fun2()成员</span></span><br><span class="line">    </span><br><span class="line">    Person&lt;MyClass2&gt; p2;</span><br><span class="line">	p2.<span class="built_in">fun2</span>();<span class="comment">//显示：MyClass2的fun2的调用</span></span><br><span class="line">	<span class="comment">//p2.fun1();错误，MyClass2没有fun1()成员</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">test01</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出结果：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">MyClass1的fun1的调用</span><br><span class="line">MyClass2的fun2的调用</span><br></pre></td></tr></table></figure></div>

<h3 id="类模板对象做函数参数"><a href="#类模板对象做函数参数" class="headerlink" title="类模板对象做函数参数"></a>类模板对象做函数参数</h3><hr>
<p>类模板实例化出来的对象像函数传参有三种传入方式：</p>
<ul>
<li><p>指定传入的类型：直接显示对象的数据类型</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>,<span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age) :<span class="built_in">name</span>(name), <span class="built_in">age</span>(age)</span><br><span class="line">	&#123;&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;age &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	T1 name;</span><br><span class="line">	T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">//指定传入类型</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">printpPerson1</span><span class="params">(Person&lt;string, <span class="type">int</span>&gt;&amp; p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	p.<span class="built_in">show</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Person&lt;string, <span class="type">int</span>&gt;<span class="built_in">p1</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>);</span><br><span class="line">    <span class="built_in">printpPerson1</span>(p1);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure></div>


</li>
<li><p>参数模板化：将对象中的参数变为模板进行传递</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>,<span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age) :<span class="built_in">name</span>(name), <span class="built_in">age</span>(age)</span><br><span class="line">	&#123;&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;age &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	T1 name;</span><br><span class="line">	T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//参数模板化</span></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">class</span> T1, <span class="keyword">class</span> T2&gt;</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">printPerson2</span><span class="params">(Person&lt;T1, T2&gt;&amp; p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	p.<span class="built_in">show</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Person&lt;string, <span class="type">int</span>&gt;<span class="built_in">p1</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>);</span><br><span class="line">    <span class="built_in">printpPerson2</span>(p1);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>


</li>
<li><p>整个类模板化：将这个对象类型模板化进行传递</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>,<span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age) :<span class="built_in">name</span>(name), <span class="built_in">age</span>(age)</span><br><span class="line">	&#123;&#125;</span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">()</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;age &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	T1 name;</span><br><span class="line">	T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//整个类模板化</span></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">class</span> T&gt;</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">printPerson3</span><span class="params">(T&amp; p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	p.<span class="built_in">show</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Person&lt;string, <span class="type">int</span>&gt;<span class="built_in">p1</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">20</span>);</span><br><span class="line">    <span class="built_in">printpPerson3</span>(p1);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h3 id="类模板与继承"><a href="#类模板与继承" class="headerlink" title="类模板与继承"></a>类模板与继承</h3><hr>
<ul>
<li><p>当子类继承的父类是一个类模板时，子类在声明的时候，要指定出父类中“<code>T</code>”的类型，如果不指定。编译器无法给子类分配内存</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">father</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T m;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//class son :public father //错误，必须要知道父类中的T类型，才能继承给子类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">son</span> :<span class="keyword">public</span> father&lt;<span class="type">int</span>&gt;</span><br><span class="line">&#123;</span><br><span class="line">    </span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>如果想灵活指定出父类中“<code>T</code>”的类型，子类也需变为类模板</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">father</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T m;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>,<span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">son</span> :<span class="keyword">public</span> father&lt;T2&gt;<span class="comment">//T1指定成子类自己的类型，T2指定成父类的类型</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	T1 obj;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	son&lt;<span class="type">int</span>, string&gt; s1;</span><br><span class="line">	s1.m = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">	s1.obj = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; s1.m &lt;&lt; endl;</span><br><span class="line">	cout &lt;&lt; s1.obj &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">test01</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&gt;nul&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<h3 id="类模板成员函数的类外实现"><a href="#类模板成员函数的类外实现" class="headerlink" title="类模板成员函数的类外实现"></a>类模板成员函数的类外实现</h3><hr>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>,<span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age) :<span class="built_in">name</span>(name), <span class="built_in">age</span>(age);</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">	T1 name;</span><br><span class="line">	T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line">Person&lt;T1, T2&gt;::<span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="type">void</span> Person&lt;T1, T2&gt;::<span class="built_in">show</span>()</span><br><span class="line">&#123;</span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; <span class="keyword">this</span>-&gt;age &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h3 id="类模板的分文件编写"><a href="#类模板的分文件编写" class="headerlink" title="类模板的分文件编写"></a>类模板的分文件编写</h3><hr>
<p>普通类的分文件编写是在<code>.h</code>中写声明，<code>.cpp</code>中写定义，对于类模板如果采用这种写法则会报错。类模板中成员函数创建时机是在调用阶段，如果采用分普通的分文件方式编写，即在<code>.h</code>文件中写声明，在<code>.cpp</code>文件中写定义，会导致<code>.cpp</code>中的定义链接不到。</p>
<p>报错原因：</p>
<ul>
<li>采用普通分文件编写时，首先包含了<code>.h</code>头文件，编译器知道了类模板的存在，但是类模板中的成员函数在调用时才会创建，所以此时编译器不会去“寻找”成员函数的定义，之后去调用时，因为没有包含<code>.cpp</code>文件<code>.h</code>文件中也没有包含<code>.cpp</code>文件，因此编译器无法链接到类模板中的成员函数。</li>
</ul>
<p>解决方案：</p>
<ul>
<li>直接包含<code>.cpp</code>源文件。示例（假设有一个Person的类模板，在<code>.h</code>中声明，在<code>.cpp</code>中定义）：把<code>#include &quot;Person.h&quot;</code>变为<code>#include &quot;Person.cpp&quot;</code>。</li>
<li>将声明<code>.h</code>文件和实现<code>.cpp</code>文件写到同一个文件中，并更改后缀名为<code>.hpp</code>。<code>hpp</code>是约定俗成的名称，并不是强制的。</li>
<li>采用传统分文件方式编写，在<code>.h</code>文件最后包含上<code>.cpp</code>文件，同时使用<code>#pragma once</code>防止头文件重复包含。在主函数文件中包含<code>.h</code>文件即可。</li>
</ul>
<h3 id="类模板与友元"><a href="#类模板与友元" class="headerlink" title="类模板与友元"></a>类模板与友元</h3><hr>
<p>在类模板中编写友元函数或友元类时，需要注意以下几点：</p>
<ul>
<li>友元函数或友元类的声明位置：友元函数或友元类的声明应该放在类模板内部，并在需要访问私有或保护成员的地方进行声明。通常，在类模板的定义之前声明友元函数或友元类，以便让编译器知道这些函数或类是模板类的友元。</li>
<li>模板参数的传递：如果友元函数或友元类也是一个模板，并且它的模板参数与包含它的类模板的模板参数不同，需要显式传递模板参数。这可以通过将类模板的模板参数列表添加到友元函数或友元类的声明中来实现。</li>
<li>定义位置的选择：友元函数或友元类的定义可以放在类模板的内部或外部。如果将定义放在类模板的内部，需要注意它们是每个实例化的模板类的独立定义，而不是共享的。如果将定义放在类模板的外部，通常需要在定义之前使用<code>template</code>关键字以指明它是一个类模板的友元。</li>
</ul>
<p>友元函数：</p>
<ul>
<li><p>类内声明和定义：直接在类内声明友元并定义即可</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="function"><span class="keyword">friend</span> <span class="type">void</span> <span class="title">show</span><span class="params">(Person&lt;T1, T2&gt;p)</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		std::cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; p.name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; p.age &lt;&lt; std::endl;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">		<span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">	&#125;;</span><br><span class="line">	T1 name;</span><br><span class="line">	T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Person&lt;std::string, <span class="type">int</span>&gt;<span class="built_in">p1</span>(<span class="string">&quot;张三&quot;</span>,<span class="number">20</span>);</span><br><span class="line">	<span class="built_in">show</span>(p1);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出结果：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">姓名：张三  年龄：20</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>类内声明类外定义：需要提前让编译器知道友元函数的存在</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T1</span>, <span class="keyword">class</span> <span class="title class_">T2</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//友元函数的声明</span></span><br><span class="line">    <span class="function"><span class="keyword">template</span>&lt;<span class="keyword">class</span> t3, <span class="keyword">class</span> t4&gt;</span></span><br><span class="line"><span class="function">    <span class="keyword">friend</span> <span class="type">void</span> <span class="title">show</span><span class="params">(Person&lt;t3, t4&gt;p)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Person</span>(T1 name, T2 age)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;name = name;</span><br><span class="line">        <span class="keyword">this</span>-&gt;age = age;</span><br><span class="line">    &#125;;</span><br><span class="line">    T1 name;</span><br><span class="line">    T2 age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//友元函数的定义</span></span><br><span class="line"><span class="function"><span class="keyword">template</span>&lt;<span class="keyword">class</span> t3, <span class="keyword">class</span> t4&gt;</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">show</span><span class="params">(Person&lt;t3, t4&gt;p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;姓名：&quot;</span> &lt;&lt; p.name &lt;&lt; <span class="string">&quot;  年龄：&quot;</span> &lt;&lt; p.age &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    Person&lt;std::string, <span class="type">int</span>&gt;<span class="built_in">p1</span>(<span class="string">&quot;张三&quot;</span>,<span class="number">20</span>);</span><br><span class="line">	<span class="built_in">show</span>(p1);  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<p>友元类：</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TemplateClass</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">TemplateClass</span>(T data)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">this</span>-&gt;m_date = date;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 友元类的声明</span></span><br><span class="line">    <span class="keyword">template</span> &lt;<span class="keyword">class</span> <span class="title class_">U</span>&gt;</span><br><span class="line">    <span class="keyword">friend</span> <span class="keyword">class</span> <span class="title class_">FriendClass</span>;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    T m_data;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 友元类的定义</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">FriendClass</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">FriendClass</span>(<span class="type">const</span> TemplateClass&lt;T&gt;&amp; obj)</span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Friend Class: &quot;</span> &lt;&lt; obj.m_data &lt;&lt; std::endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div>

<p>友元函数或友元类的声明应该放在类模板内部，并在需要访问私有或保护成员的地方进行声明。通常，在类模板的定义之前声明友元函数或友元类，以便让编译器知道这些函数或类是模板类的友元。</p>
<h3 id="关于typename和class"><a href="#关于typename和class" class="headerlink" title="关于typename和class"></a>关于<code>typename</code>和<code>class</code></h3><hr>
<p>在C++模板中，<code>typename</code>和<code>class</code>关键字用于声明模板参数，它们在大多数情况下是可以互换使用的，没有本质的区别。</p>
<p>然而，它们在某些情况下具有一些细微的区别：</p>
<ul>
<li><p>模板参数的默认关键字：当定义模板参数时，<code>class</code>可以使用默认关键字<code>class</code>或<code>typename</code>。</p>
<p>例如：<code>template &lt;class T&gt;</code> 或 <code>template &lt;typename T&gt;</code>。这两者是等效的，可以互换使用。</p>
</li>
<li><p>嵌套依赖名称：在模板中使用嵌套依赖名称时，必须使用<code>typename</code>关键字。</p>
<p>例如，当在类模板的成员函数中使用依赖于模板参数的类型时，需要使用<code>typename</code>关键字来指示该名称是一个类型。例如：<code>typename T::value_type</code>。</p>
</li>
<li><p>模板参数作为模板参数：当模板参数本身是一个模板时，必须使用<code>class</code>关键字。</p>
<p>例如，当模板参数是一个模板类时，使用<code>class</code>关键字来声明它，如：<code>template &lt;class Container&gt;</code>。</p>
</li>
</ul>
<p><code>typename</code>和<code>class</code>在大多数情况下可以互换使用，没有本质的区别。在某些特定的情况下，使用<code>typename</code>关键字是必要的，例如处理嵌套依赖名称时。</p>
<p>一般来说，根据个人偏好或项目风格指南选择使用<code>typename</code>还是<code>class</code>。</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyContainer</span> </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">typedef</span> T value_type;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> Container&gt;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">printValueType</span><span class="params">(Container container)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 错误示例：尝试使用未指定类型的依赖名称</span></span><br><span class="line">    <span class="comment">// 此处必须使用 typename 关键字</span></span><br><span class="line">    <span class="comment">// std::cout &lt;&lt; Container::value_type &lt;&lt; std::endl;  // 编译错误</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 正确示例：使用 typename 关键字指示依赖名称是类型</span></span><br><span class="line">    <span class="keyword">typename</span> Container::value_type value;</span><br><span class="line">    std::cout &lt;&lt; <span class="built_in">typeid</span>(value).<span class="built_in">name</span>() &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    MyContainer&lt;<span class="type">int</span>&gt; container;</span><br><span class="line">    <span class="built_in">printValueType</span>(container);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在上述示例中，我们定义了一个模板类 <code>MyContainer</code>，其中包含一个内部类型别名 <code>value_type</code>。</p>
<p>然后，我们定义了一个模板函数 <code>printValueType</code>，该函数接受一个模板参数 <code>Container</code>，并尝试访问 <code>Container</code> 类型的 <code>value_type</code>。</p>
<p>在错误示例中，我们未使用 <code>typename</code> 关键字，编译器会报错，因为它无法确定 <code>Container::value_type</code> 是一个类型还是一个成员变量。</p>
<p>而在正确示例中，我们使用 <code>typename</code> 关键字来明确告诉编译器 <code>Container::value_type</code> 是一个类型。</p>
<p>总结：</p>
<ul>
<li>在涉及到嵌套依赖名称时，必须使用 <code>typename</code> 关键字来指示该名称是一个类型。</li>
<li>在模板参数本身是一个模板时，必须使用 <code>class</code> 关键字来声明它，例如 <code>template &lt;class Container&gt;</code>。</li>
</ul>
<h1 id="STL部分"><a href="#STL部分" class="headerlink" title="STL部分"></a>STL部分</h1><h2 id="说明"><a href="#说明" class="headerlink" title="&#x3D;&#x3D;说明&#x3D;&#x3D;"></a>&#x3D;&#x3D;说明&#x3D;&#x3D;</h2><p>本章的编写根据C++98标准，对于新标准的内容只是略有涉及，部章的部分内容在新的标准中也许是不正确的。</p>
<p>本章的大部分内容只编写了常见、常用的内容，对于不常用、不常见的用法或新标准中新增的、更改的内容详细请自行参阅手册。</p>
<p>截止到C++20标准，<code>STL</code>（标准模板库）提供了以下容器：</p>
<ol>
<li><code>std::array</code>: 固定大小的数组容器。</li>
<li><code>std::vector</code>: 动态数组，可根据需要自动调整大小。</li>
<li><code>std::deque</code>: 双端队列，允许在两端高效地添加和删除元素。</li>
<li><code>std::list</code>: 双向链表。</li>
<li><code>std::forward_list</code>: 单向链表。</li>
<li><code>std::set</code>: 按升序排序的唯一元素集合。</li>
<li><code>std::multiset</code>: 按升序排序的允许重复元素的集合。</li>
<li><code>std::map</code>: 键-值对的有序映射，按键的升序排序。</li>
<li><code>std::multimap</code>: 键-值对的有序映射，允许重复的键。</li>
<li><code>std::unordered_set</code>: 哈希集合，不保证元素顺序。</li>
<li><code>std::unordered_multiset</code>: 哈希集合，允许重复元素，不保证元素顺序。</li>
<li><code>std::unordered_map</code>: 键-值对的哈希映射，不保证元素顺序。</li>
<li><code>std::unordered_multimap</code>: 键-值对的哈希映射，允许重复的键，不保证元素顺序。</li>
<li><code>std::stack</code>: 栈，后进先出（LIFO）的数据结构适配器。</li>
<li><code>std::queue</code>: 队列，先进先出（FIFO）的数据结构适配器。</li>
<li><code>std::priority_queue</code>: 优先队列，根据优先级进行排序的数据结构适配器。</li>
</ol>
<p>这些容器提供了不同的功能和性能特点，可以根据具体的需求选择合适的容器。</p>
<p>以下是C++11标准引入的新容器：</p>
<ol>
<li><code>std::array</code>: 固定大小的数组容器。</li>
<li><code>std::unordered_set</code>: 哈希集合，不保证元素顺序。</li>
<li><code>std::unordered_multiset</code>: 哈希集合，允许重复元素，不保证元素顺序。</li>
<li><code>std::unordered_map</code>: 键-值对的哈希映射，不保证元素顺序。</li>
<li><code>std::unordered_multimap</code>: 键-值对的哈希映射，允许重复的键，不保证元素顺序。</li>
</ol>
<p>以下是C++17标准引入的新容器：</p>
<ol>
<li><code>std::optional</code>: 可选值容器，可以表示一个可能存在或不存在的值。</li>
<li><code>std::variant</code>: 可变类型容器，可以容纳多个可能的类型中的一个值。</li>
<li><code>std::any</code>: 任意类型容器，可以容纳任意类型的值。</li>
<li><code>std::string_view</code>: 字符串视图，用于非拥有权的字符串操作。</li>
</ol>
<p>从C++20开始，没有引入新的容器类型。</p>
<h2 id="string容器"><a href="#string容器" class="headerlink" title="string容器"></a><code>string</code>容器</h2><hr>
<h3 id="构造函数-1"><a href="#构造函数-1" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">string</span>();							<span class="comment">//创建一个空的字符串例如: string str;</span></span><br><span class="line"><span class="built_in">string</span>(<span class="type">const</span> <span class="type">char</span>* s);				<span class="comment">//使用C风格字符串s初始化</span></span><br><span class="line"><span class="built_in">string</span>(<span class="type">const</span> string&amp; str);			<span class="comment">//使用一个string对象初始化另一个string对象</span></span><br><span class="line"><span class="built_in">string</span>(<span class="type">int</span> n，<span class="type">char</span> c);              <span class="comment">//使用n个字符c初始化</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值"><a href="#赋值" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">string&amp; <span class="keyword">operator</span>=(<span class="type">const</span> <span class="type">char</span>* s);			<span class="comment">//char*类型字符串赋值给当前的字符串</span></span><br><span class="line">string&amp; <span class="keyword">operator</span>=(<span class="type">const</span> string &amp;s);			<span class="comment">//把字符串s赋给当前的字符串</span></span><br><span class="line">string&amp; <span class="keyword">operator</span>=(<span class="type">char</span> c);					<span class="comment">//字符赋值给当前的字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">assign</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *s)</span></span>;				<span class="comment">//把字符串s赋给当前的字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">assign</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *s, <span class="type">int</span> n)</span></span>;		<span class="comment">//把字符串s的前n个字符赋给当前的字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">assign</span><span class="params">(<span class="type">const</span> string &amp;s)</span> </span>;			<span class="comment">//把字符串s赋给当前字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">assign</span><span class="params">(<span class="type">int</span> n，<span class="type">char</span> c)</span></span>;              <span class="comment">//用n个字符c赋给当前字符串</span></span><br></pre></td></tr></table></figure></div>

<h3 id="拼接"><a href="#拼接" class="headerlink" title="拼接"></a>拼接</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">string&amp; <span class="keyword">operator</span>+=( <span class="type">const</span> <span class="type">char</span>* str);               <span class="comment">//重载+=操作符</span></span><br><span class="line">string&amp; <span class="keyword">operator</span>+=( <span class="type">const</span> <span class="type">char</span> c);                  <span class="comment">//重载+=操作符</span></span><br><span class="line">string&amp; <span class="keyword">operator</span>+=( <span class="type">const</span> string&amp; str);             <span class="comment">//重载+=操作符</span></span><br><span class="line"><span class="function">string&amp; <span class="title">append</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *s )</span> </span>;                    <span class="comment">//把字符串s连接到当前字符串结尾</span></span><br><span class="line"><span class="function">string&amp; <span class="title">append</span><span class="params">( <span class="type">const</span> <span class="type">char</span> *s, <span class="type">int</span> n)</span></span>;              <span class="comment">//把字符串s的前n个字符连接到当前字符串结尾</span></span><br><span class="line"><span class="function">string&amp; <span class="title">append</span><span class="params">(<span class="type">const</span> string &amp;s )</span> </span>;                  <span class="comment">//同operator+=(const string&amp; str)</span></span><br><span class="line"><span class="function">string&amp; <span class="title">append</span><span class="params">(<span class="type">const</span> string &amp;s，<span class="type">int</span> pos,<span class="type">int</span> n)</span></span>;     <span class="comment">//字符串s中从pos开始的n个字符连接到字符串结尾</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">push_back</span> <span class="params">(<span class="type">char</span> c)</span></span>;						<span class="comment">//它将字符 c 附加到字符串的末尾，将其长度增加一</span></span><br></pre></td></tr></table></figure></div>

<h3 id="查找、替换"><a href="#查找、替换" class="headerlink" title="查找、替换"></a>查找、替换</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">const</span> string&amp; str, <span class="type">int</span> pos = <span class="number">0</span>)</span> <span class="type">const</span></span>;         <span class="comment">//查找str第一次出现位置,从pos开始查找</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* s, <span class="type">int</span> pos - e)</span> <span class="type">const</span></span>;             <span class="comment">//查找s第一次出现位置,从pos开始查找</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* s , <span class="type">int</span> pos， <span class="type">int</span> n)</span> <span class="type">const</span></span>;        <span class="comment">//从pos位置查找s的前n个字符第一次位置</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">const</span> <span class="type">char</span> c, <span class="type">int</span> pos = e)</span> <span class="type">const</span></span>;              <span class="comment">//查找字符c第一次出现位置</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">rfind</span><span class="params">(<span class="type">const</span> string&amp; str, <span class="type">int</span> pos = npos)</span> <span class="type">const</span></span>;     <span class="comment">//查找str最后一次位置,从pos开始查找</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">rfind</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* s, <span class="type">int</span> pos = npos)</span> <span class="type">const</span></span>;         <span class="comment">//查找s最后一次出现位置,从pos开始查找</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">rfind</span><span class="params">(<span class="type">const</span> <span class="type">char</span>* s, <span class="type">int</span> pos， <span class="type">int</span> n)</span> <span class="type">const</span></span>;        <span class="comment">//从pos查找s的前n个字符最后一次位置</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">rfind</span><span class="params">(<span class="type">const</span> <span class="type">char</span> c, <span class="type">int</span> pos = e)</span> <span class="type">const</span></span>;             <span class="comment">//查找字符c最后一次出现位置</span></span><br><span class="line"></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(<span class="type">size_t</span> pos, <span class="type">size_t</span> len, <span class="type">const</span> string&amp; str)</span></span>; 					<span class="comment">//替换从pos开始len个字符为字符串str  </span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(<span class="type">size_t</span> pos, <span class="type">size_t</span> len, <span class="type">const</span> <span class="type">char</span>* s)</span></span>;   						<span class="comment">//替换从pos开始的len个字符为C风格字符串s</span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span><span class="params">(<span class="type">size_t</span> pos, <span class="type">size_t</span> len, <span class="type">const</span> <span class="type">char</span>* s, <span class="type">size_t</span> n)</span></span>;  				<span class="comment">//用s的前n个字符替换从pos开始长度为len的子串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(<span class="type">size_t</span> pos, <span class="type">size_t</span> len, <span class="type">size_t</span> n, <span class="type">char</span> c)</span></span>; 					<span class="comment">//用n个c字符替换从pos开始长度为len的子串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(<span class="type">size_t</span> pos, <span class="type">size_t</span> len, <span class="type">const</span> string&amp; str, <span class="type">size_t</span> subpos, <span class="type">size_t</span> sublen)</span></span>;</span><br><span class="line"><span class="comment">//用str字符串[subpos,sublen)内的字串替换[pos,len)内的字符</span></span><br><span class="line"></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(const_iterator i1, const_iterator i2, <span class="type">const</span> string&amp; str)</span></span>;		<span class="comment">//用str替换迭代器起始位置和结束位置的字符 </span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(const_iterator i1, const_iterator i2, <span class="type">const</span> <span class="type">char</span>* s)</span></span>; 			<span class="comment">//用C风格字符串s替换迭代器起始位置和结束位置的字符 </span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(const_iterator i1, const_iterator i2, <span class="type">const</span> <span class="type">char</span>* s, <span class="type">size_t</span> n)</span></span>; <span class="comment">//用s的前n个字符替换指定迭代器位置(从i1到i2)的字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">replace</span> <span class="params">(const_iterator i1, const_iterator i2, <span class="type">size_t</span> n, <span class="type">char</span> c)</span></span>; 		<span class="comment">//n个c字符替换从指定迭代器位置(从i1到i2)的字符串</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap</span> <span class="params">(string&amp; str)</span></span>;	<span class="comment">//交换两个字符串的内容</span></span><br></pre></td></tr></table></figure></div>

<h3 id="比较"><a href="#比较" class="headerlink" title="比较"></a>比较</h3><hr>
<p>比较方式：字符串比较是按字符的ASCII码进行对比</p>
<p>相等：返回0</p>
<p>前者大于后者：返回1</p>
<p>前者小于后者：返回-1</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">compare</span><span class="params">(<span class="type">const</span> string &amp;s)</span> <span class="type">const</span></span>;		<span class="comment">//与C++风格字符串s比较</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">compare</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *s )</span> <span class="type">const</span></span>;		<span class="comment">//与C风格字符串s比较</span></span><br></pre></td></tr></table></figure></div>

<h3 id="获取单个字符"><a href="#获取单个字符" class="headerlink" title="获取单个字符"></a>获取单个字符</h3><hr>
<p><code>C++11</code>声明：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">const</span> <span class="type">char</span>&amp; <span class="keyword">operator</span>[] (<span class="type">size_t</span> pos) <span class="type">const</span>;	<span class="comment">//通过[]类似数组下标方式取字符</span></span><br><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>&amp; <span class="title">at</span> <span class="params">(<span class="type">size_t</span> pos)</span> <span class="type">const</span></span>;			<span class="comment">//通过at方法获取第pos个字符</span></span><br><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>&amp; <span class="title">back</span><span class="params">()</span> <span class="type">const</span></span>;					<span class="comment">//返回对字符串最后一个字符的引用</span></span><br><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>&amp; <span class="title">front</span><span class="params">()</span> <span class="type">const</span></span>;					<span class="comment">//返回对字符串第一个字符的引用</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除"><a href="#插入和删除" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string&amp; <span class="title">insert</span><span class="params">(<span class="type">int</span> pos, <span class="type">const</span> <span class="type">char</span>* s)</span></span>;				<span class="comment">//插入字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">insert</span><span class="params">(<span class="type">int</span> pos, <span class="type">const</span> string&amp; str)</span></span>;			<span class="comment">//插入字符串</span></span><br><span class="line"><span class="function">string&amp; <span class="title">insert</span><span class="params">(<span class="type">int</span> pos, <span class="type">int</span> n,<span class="type">char</span> c)</span></span>;				<span class="comment">//在指定位置插入n个字符c	</span></span><br></pre></td></tr></table></figure></div>

<p><code>C++11</code>声明：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string&amp; <span class="title">erase</span> <span class="params">(<span class="type">size_t</span> pos = <span class="number">0</span>, <span class="type">size_t</span> len = npos)</span></span>;	<span class="comment">//删除从pos开始的len个字符</span></span><br><span class="line"><span class="function">string&amp; <span class="title">erase</span><span class="params">(<span class="type">const</span> <span class="type">size_t</span> Off = <span class="number">0</span>)</span></span>;				<span class="comment">//删除下标从Off开始直到字符串结尾的元素</span></span><br><span class="line"><span class="function">iterator <span class="title">erase</span> <span class="params">(iterator position)</span></span>;					<span class="comment">//删除迭代器指向的元素，返回值是指向删除元素的下一个元素的迭代器</span></span><br><span class="line"><span class="function">iterator <span class="title">erase</span> <span class="params">(iterator first, iterator last)</span></span>;		<span class="comment">//删除迭代器指定范围[first, last)内的字符串，返回值是指向被删除子串的下一个元素的迭代器</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">clear</span><span class="params">()</span> <span class="keyword">noexcept</span></span>;								<span class="comment">//擦除字符串的内容，使之变成一个空字符串</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pop_back</span><span class="params">()</span></span>;									<span class="comment">//擦除字符串的最后一个字符，从而有效地将其长度减少一个</span></span><br></pre></td></tr></table></figure></div>

<h3 id="获取子串"><a href="#获取子串" class="headerlink" title="获取子串"></a>获取子串</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">substr</span> <span class="params">(<span class="type">size_t</span> pos = <span class="number">0</span>, <span class="type">size_t</span> len = npos)</span> <span class="type">const</span></span>;	<span class="comment">//返回由pos开始的n个字符组成的字符串</span></span><br></pre></td></tr></table></figure></div>

<h3 id="长度和容量"><a href="#长度和容量" class="headerlink" title="长度和容量"></a>长度和容量</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">size_t</span> <span class="title">size</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;		<span class="comment">//以字节为单位返回字符串的长度，英文返回值等于字符数量，中文翻倍</span></span><br><span class="line"><span class="function"><span class="type">size_t</span> <span class="title">length</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;		<span class="comment">//和size()作用相同，没有区别</span></span><br><span class="line"><span class="function"><span class="type">size_t</span> <span class="title">max_size</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;	<span class="comment">//返回字符串可以达到的最大长度</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">resize</span> <span class="params">(<span class="type">size_t</span> n, <span class="type">char</span> c)</span></span>;		<span class="comment">//将字符串的大小调整为n个字符的长度,可选：如果n大于现有长度，用字符c填充到新的空间</span></span><br><span class="line"><span class="function"><span class="type">size_t</span> <span class="title">capacity</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;	<span class="comment">//返回当前为字符串分配的存储空间的大小，以字节表示</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">reserve</span> <span class="params">(<span class="type">size_t</span> n = <span class="number">0</span>)</span></span>;		<span class="comment">//改变容量，预留n个字节的空间，减少拷贝、复制等操作时的运行时间</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">shrink_to_fit</span><span class="params">()</span></span>;				<span class="comment">//使字符串减小其分配容量以适应字符内容的大小</span></span><br></pre></td></tr></table></figure></div>

<h3 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h3><hr>
<p>待整理：</p>
<p><a class="link"   target="_blank" rel="noopener" href="https://www.w3schools.cn/cpp_standard_library/string.html" >C++ 标准库 -  (w3schools.cn) <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>* <span class="title">c_str</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;							<span class="comment">//用于获得等效的 C风格字符串</span></span><br><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>* <span class="title">data</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;							<span class="comment">//C++11后与c_str等效，没有区别</span></span><br><span class="line"><span class="function"><span class="type">size_t</span> <span class="title">copy</span> <span class="params">(<span class="type">char</span>* s, <span class="type">size_t</span> len, <span class="type">size_t</span> pos = <span class="number">0</span>)</span> <span class="type">const</span></span>;	  <span class="comment">//在string对象中从第pos个位置开始，取出len个字符存放到char数组s中</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">empty</span><span class="params">()</span> <span class="type">const</span> <span class="keyword">noexcept</span></span>;								<span class="comment">//返回字符串是否为空（即其长度是否为 0）</span></span><br></pre></td></tr></table></figure></div>

<h2 id="vector容器"><a href="#vector容器" class="headerlink" title="vector容器"></a><code>vector</code>容器</h2><hr>
<h3 id="构造函数-2"><a href="#构造函数-2" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vector&lt;T&gt; v;						<span class="comment">//采用模板实现类实现，默认构造函数</span></span><br><span class="line"><span class="built_in">vector</span>(v.<span class="built_in">begin</span>() , v.<span class="built_in">end</span>() ) ;		 <span class="comment">//将v[begin(), end())区间中的元素拷贝给本身</span></span><br><span class="line"><span class="built_in">vector</span>(n,elem);					    <span class="comment">//构造函数将n个elem拷贝给本身</span></span><br><span class="line"><span class="built_in">vector</span>( <span class="type">const</span> vector &amp;vek ) ;		<span class="comment">//拷贝构造函数。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值-1"><a href="#赋值-1" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vector&amp; <span class="keyword">operator</span>=( <span class="type">const</span> vector &amp;vec);<span class="comment">//重载等号操作符</span></span><br><span class="line"><span class="built_in">assign</span>( beg, end) ;<span class="comment">//将[beg, end)区间中的数据拷贝赋值给本身。</span></span><br><span class="line"><span class="built_in">assign</span>(n,elem);<span class="comment">//将n个elem拷贝赋值给本身。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容量和大小"><a href="#容量和大小" class="headerlink" title="容量和大小"></a>容量和大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">empty</span>( ) ;<span class="comment">//判断容器是否为空</span></span><br><span class="line"><span class="built_in">capacity</span>();<span class="comment">//容器的容量</span></span><br><span class="line"><span class="built_in">size</span>();<span class="comment">//返回容器中元素的个数</span></span><br><span class="line"><span class="built_in">resize</span>(<span class="type">int</span> num ) ;<span class="comment">//重新指定容器的长度为num，若容器变长，则以默认值填充新位置。</span></span><br><span class="line">				<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除。</span></span><br><span class="line"><span class="built_in">resize</span>(<span class="type">int</span> num，elem);<span class="comment">//重新指定容器的长度为num，若容器变长，则以elem值填充新位置。</span></span><br><span class="line">					<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除-1"><a href="#插入和删除-1" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">push_back</span>(ele);<span class="comment">//尾部插入元素ele</span></span><br><span class="line"><span class="built_in">pop_back</span>();<span class="comment">//删除最后一个元素</span></span><br><span class="line"><span class="built_in">insert</span>(const_iterator pos, ele) ;<span class="comment">//迭代器指向位置pos插入元素ele</span></span><br><span class="line"><span class="built_in">insert</span>(const_iterator pos, <span class="type">int</span> count,ele);<span class="comment">//迭代器指向位置pos插入count个元素ele</span></span><br><span class="line"><span class="built_in">erase</span>( const_iterator pos ) ;<span class="comment">//删除迭代器指向的元素</span></span><br><span class="line"><span class="built_in">erase</span>(const_iterator start，const_iterator end);<span class="comment">//删除迭代器从start到end之间的元素</span></span><br><span class="line"><span class="built_in">clear</span>() ;<span class="comment">//删除容器中所有元素</span></span><br></pre></td></tr></table></figure></div>

<h3 id="存、取"><a href="#存、取" class="headerlink" title="存、取"></a>存、取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">at</span>(<span class="type">int</span> idx ) ;<span class="comment">//返回索引idx所指的数据</span></span><br><span class="line"><span class="keyword">operator</span>[];<span class="comment">//返回索引idx所指的数据</span></span><br><span class="line"><span class="built_in">front</span>( );<span class="comment">//返回容器中第一个数据元素</span></span><br><span class="line"><span class="built_in">back</span>();<span class="comment">//返回容器中最后一个数据元素</span></span><br></pre></td></tr></table></figure></div>

<h3 id="交换"><a href="#交换" class="headerlink" title="交换"></a>交换</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">swap</span>(vec);<span class="comment">//将vec与本身的元素互换</span></span><br></pre></td></tr></table></figure></div>

<h3 id="预留空间"><a href="#预留空间" class="headerlink" title="预留空间"></a>预留空间</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">reserve</span>(<span class="type">int</span> len);<span class="comment">//容器预留len个元素长度，预留位置不初始化，元素不可访问。</span></span><br></pre></td></tr></table></figure></div>

<h2 id="deque容器"><a href="#deque容器" class="headerlink" title="deque容器"></a><code>deque</code>容器</h2><hr>
<p><code>deque</code>容器是双端数组，可以对头和尾进行插入和删除。</p>
<p>与<code>vector</code>的区别：</p>
<ul>
<li><code>vector</code>对于头部的插入删除效率低，数据量越大，效率越低</li>
<li><code>deque</code>相对而言，对头部的插入删除速度回比<code>vector</code>快</li>
<li><code>vector</code>访问元素时的速度会比<code>deque</code>快,这和两者内部实现有关</li>
</ul>
<h3 id="构造函数-3"><a href="#构造函数-3" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deque&lt;T&gt; deqT;				<span class="comment">//默认构造形式</span></span><br><span class="line"><span class="built_in">deque</span>(beg, end) ;			<span class="comment">//构造函数将[beg, end)区间中的元素拷贝给本身。</span></span><br><span class="line"><span class="built_in">deque</span>(n,elem);				<span class="comment">//构造函数将n个elem拷贝给本身。</span></span><br><span class="line"><span class="built_in">deque</span>(<span class="type">const</span> deque &amp;deq); 	<span class="comment">//拷贝构造函数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值-2"><a href="#赋值-2" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">deque&amp; <span class="keyword">operator</span>=(<span class="type">const</span> deque &amp;deq);			<span class="comment">//重载等号操作符</span></span><br><span class="line"><span class="built_in">assign</span>(beg, end) ;							<span class="comment">//将[beg, end)区间中的数据拷贝赋值给本身。</span></span><br><span class="line"><span class="built_in">assign</span>(n,elem ) ;							<span class="comment">//将n个elem拷贝赋值给本身。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容器大小"><a href="#容器大小" class="headerlink" title="容器大小"></a>容器大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">deque.<span class="built_in">empty</span>();				<span class="comment">//判断容器是否为空</span></span><br><span class="line">deque.<span class="built_in">size</span>();				<span class="comment">//返回容器中元素的个数</span></span><br><span class="line">deque.<span class="built_in">resize</span>(num);			<span class="comment">//重新指定容器的长度为num,若容器变长，则以默认值填充新位置。</span></span><br><span class="line">							<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除。</span></span><br><span class="line">deque.<span class="built_in">resize</span>(num，elem) ;	<span class="comment">//重新指定容器的长度为num,若容器变长，则以elem值填充新位置。</span></span><br><span class="line">							<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除-2"><a href="#插入和删除-2" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">push_back</span>(elem) ;			<span class="comment">//在容器尾部添加一个数据</span></span><br><span class="line"><span class="built_in">push_front</span>(elem) ;			<span class="comment">//在容器头部插入一个数据</span></span><br><span class="line"><span class="built_in">pop_back</span>() ;				<span class="comment">//删除容器最后一个数据</span></span><br><span class="line"><span class="built_in">pop_front</span>();				<span class="comment">//删除容器第一个数据</span></span><br><span class="line"><span class="built_in">insert</span>(pos,elem);			<span class="comment">//在pos位置插入一个elem元素的拷贝，返回新数据的位置。</span></span><br><span class="line"><span class="built_in">insert</span>(pos,n,elem);			<span class="comment">//在pos位置插入n个elem数据，无返回值。</span></span><br><span class="line"><span class="built_in">insert</span>( pos,beg,end);		<span class="comment">//在pos位置插入[beg,end)区间的数据，无返回值。</span></span><br><span class="line"><span class="built_in">clear</span>();					<span class="comment">//清空容器的所有数据</span></span><br><span class="line"><span class="built_in">erase</span>(beg,end);				<span class="comment">//删除[beg,end)区间的数据，返回下一个数据的位置。</span></span><br><span class="line"><span class="built_in">erase</span>(pos) ;				<span class="comment">//删除pos位置的数据，返回下一个数据的位置。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="存、取-1"><a href="#存、取-1" class="headerlink" title="存、取"></a>存、取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">at</span>(<span class="type">int</span> idx);		<span class="comment">//返回索引idx所指的数据</span></span><br><span class="line"><span class="keyword">operator</span>[];			<span class="comment">//返回索引idx所指的数据</span></span><br><span class="line"><span class="built_in">front</span>();			<span class="comment">//返回容器中第一个数据元素</span></span><br><span class="line"><span class="built_in">back</span>();				<span class="comment">//返回容器中最后一个数据元素</span></span><br></pre></td></tr></table></figure></div>

<h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><hr>
<p>示例用法，之后会详细讲：</p>
<p>默认从大到小排序：</p>
<p>需要包含头文件<code>#include &lt;algorithm&gt;</code></p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sort</span>(iterator beg, iterator end);	<span class="comment">//对beg和end区间内元素进行排序</span></span><br></pre></td></tr></table></figure></div>

<h2 id="stack-容器"><a href="#stack-容器" class="headerlink" title="stack 容器"></a><code>stack</code> 容器</h2><hr>
<h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<p><code>stack</code>是一种先进后出(First In Last Out,FILO)，后进先出（LIFO）的容器，它的数据结构是栈，只有一个出口，只有栈顶元素才可以被访问，因此<code>stack</code>容器不允许被遍历。</p>
<p>向栈中插入数据叫入栈或压栈，删除栈中数据叫出栈或弹栈。</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="https://gd-hbimg.huaban.com/8c1c874271d1e5c3649251f076bb2978aeefc8ce42c2-ZHcmVA"
                     
                ></p>
<h3 id="构造函数-4"><a href="#构造函数-4" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">stack&lt;T&gt; stk;					<span class="comment">//stack采用模板类实现， stack对象的默认构造形式</span></span><br><span class="line"><span class="built_in">stack</span>(<span class="type">const</span> stack &amp;stk);		<span class="comment">//拷贝构造函数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值-3"><a href="#赋值-3" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">stack&amp; <span class="keyword">operator</span>=( <span class="type">const</span> stack &amp;stk );<span class="comment">//重载等号操作符</span></span><br></pre></td></tr></table></figure></div>

<h3 id="存、取-2"><a href="#存、取-2" class="headerlink" title="存、取"></a>存、取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">push</span>(elem) ;	<span class="comment">//向栈顶添加元素</span></span><br><span class="line"><span class="built_in">pop</span>();			<span class="comment">//从栈顶移除第一个元素</span></span><br><span class="line"><span class="built_in">top</span>( );			<span class="comment">//返回栈顶元素</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容器大小-1"><a href="#容器大小-1" class="headerlink" title="容器大小"></a>容器大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">empty</span>();<span class="comment">//判断堆栈是否为空</span></span><br><span class="line"><span class="built_in">size</span>();<span class="comment">//返回栈的大小</span></span><br></pre></td></tr></table></figure></div>

<h2 id="queue容器"><a href="#queue容器" class="headerlink" title="queue容器"></a><code>queue</code>容器</h2><hr>
<h3 id="基本概念-1"><a href="#基本概念-1" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<p><code>queue</code>是一种先进先出(First ln First Out,FIFO)的容器，其数据结构是队列，它有两个出口。</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="https://gd-hbimg.huaban.com/d02191ef7703f72efc7df591fb8587d700e2862ea867-pVoRZp"
                     
                ></p>
<ul>
<li><p>队列容器只允许从一端新增元素，从另一端移除元素。</p>
</li>
<li><p>队列中只有队头和队尾才可以被外界使用，因此队列不允许有遍历行为。</p>
</li>
</ul>
<p>队列中进数据称为：入队</p>
<p>队列中出数据称为：出队</p>
<h3 id="构造函数-5"><a href="#构造函数-5" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">queue&lt;T&gt; que;					<span class="comment">//queue采用模板类实现，queue对象的默认构造形式</span></span><br><span class="line"><span class="built_in">queue</span>(<span class="type">const</span> queue &amp;que);		<span class="comment">//拷贝构造函数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值-4"><a href="#赋值-4" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">queue&amp; <span class="keyword">operator</span>=( <span class="type">const</span> queue &amp;que);	<span class="comment">//重载等号操作符</span></span><br></pre></td></tr></table></figure></div>

<h3 id="存、取-3"><a href="#存、取-3" class="headerlink" title="存、取"></a>存、取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">push</span>(elem) ;	<span class="comment">//往队尾添加元素</span></span><br><span class="line"><span class="built_in">pop</span>();			<span class="comment">//从队头移除第一个元素</span></span><br><span class="line"><span class="built_in">back</span>();			<span class="comment">//返回最后一个元素</span></span><br><span class="line"><span class="built_in">front</span>();		<span class="comment">//返回第一个元素</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容器大小-2"><a href="#容器大小-2" class="headerlink" title="容器大小"></a>容器大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">empty</span>();	<span class="comment">//判断堆栈是否为空</span></span><br><span class="line"><span class="built_in">size</span>();		<span class="comment">//返回栈的大小</span></span><br></pre></td></tr></table></figure></div>

<h2 id="list容器"><a href="#list容器" class="headerlink" title="list容器"></a><code>list</code>容器</h2><hr>
<h3 id="基本概念-2"><a href="#基本概念-2" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<p><code>list</code>容器是一种物理存储单元上非连续的存储结构，数据元素的逻辑顺序是通过链表中的指针链接实现的。其数据结构是双向循环链表。</p>
<p>链表的组成：链表由—系列结点组成。</p>
<p>单链表结点的组成：一个是存储数据元素的数据域，另一个是存储下一个结点地址的指针域。</p>
<p>双向循环链表：其结点指针域有两个指针，分别记录上一个结点和下一个结点的地址。头结点指针域的上一个结点为尾结点，尾结点的下一个指针域为头结点，以此形成循环。</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="https://gd-hbimg.huaban.com/b6b4b891d33f1aa861bdd6ad528a5544c6622faca1d5-NTIgD6_fw1200webp"
                     
                ></p>
<p>由于链表的存储方式并不是连续的内存空间，因此<code>list</code>容器中的迭代器只支持前移和后移，属于双向迭代器。</p>
<p><code>list</code>的优点：</p>
<ul>
<li>采用动态存储分配，不会造成内存浪费和溢出。</li>
<li>链表执行插入和删除操作十分方便，修改指针即可，不需要移动大量元素。</li>
</ul>
<p>list的缺点：</p>
<ul>
<li>链表灵活，但是空间(指针域)和时间(遍历）额外耗费较大</li>
<li><code>list</code>有一个重要的性质，插入操作和删除（非迭代器指向的元素）操作都不会造成原有<code>list</code>迭代器的失效，这在vector是不成立的。</li>
</ul>
<h3 id="构造函数-6"><a href="#构造函数-6" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">list&lt;T&gt; lst;				<span class="comment">//list采用采用模板类实现,对象的默认构造形式:</span></span><br><span class="line"><span class="built_in">list</span>(beg,end) ;				<span class="comment">//构造函数将[beg, end)区间中的元素拷贝给本身。</span></span><br><span class="line"><span class="built_in">list</span>(n,elem);				<span class="comment">//构造函数将n个elem拷贝给本身。</span></span><br><span class="line"><span class="built_in">list</span>(<span class="type">const</span> list &amp;lst);		<span class="comment">//拷贝构造函数。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值和交换"><a href="#赋值和交换" class="headerlink" title="赋值和交换"></a>赋值和交换</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">assign</span>(beg, end) ;					<span class="comment">//将[beg, end)区间中的数据拷贝赋值给本身。</span></span><br><span class="line"><span class="built_in">assign</span>(n,elem);						<span class="comment">//将n个elem拷贝赋值给本身。</span></span><br><span class="line">list&amp; <span class="keyword">operator</span>=(<span class="type">const</span> list &amp;lst);	 <span class="comment">//重载等号操作符</span></span><br><span class="line"><span class="built_in">swap</span>(lst);						   <span class="comment">//将lst与本身的元素互换。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容器大小-3"><a href="#容器大小-3" class="headerlink" title="容器大小"></a>容器大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">size</span>();		<span class="comment">//返回容器中元素的个数</span></span><br><span class="line"><span class="built_in">empty</span>();	<span class="comment">//判断容器是否为空</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">resize</span>(num) ;		  <span class="comment">//重新指定容器的长度为num，若容器变长，则以默认值填充新位置。</span></span><br><span class="line">					<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除。</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">resize</span>(num,elem);	  <span class="comment">//重新指定容器的长度为num，若容器变长，则以elem值填充新位置。</span></span><br><span class="line">					<span class="comment">//如果容器变短，则末尾超出容器长度的元素被删除。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除-3"><a href="#插入和删除-3" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">push_back</span>(elem);		<span class="comment">//在容器尾部加入一个元素</span></span><br><span class="line"><span class="built_in">pop_back</span>();				<span class="comment">//删除容器中最后一个元素</span></span><br><span class="line"><span class="built_in">push_front</span>(elem);		<span class="comment">//在容器开头插入一个元素</span></span><br><span class="line"><span class="built_in">pop_front</span>();			<span class="comment">//从容器开头移除第一个元素</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">insert</span>(pos,elem);		<span class="comment">//在pos位置插elem元素的拷贝，返回新数据的位置。</span></span><br><span class="line"><span class="built_in">insert</span>(pos,n,elem);		<span class="comment">//在pos位置插入n个elem数据，无返回值。</span></span><br><span class="line"><span class="built_in">insert</span>(pos,beg,end);	<span class="comment">//在pos位置插入[beg,end)区间的数据，无返回值。</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">clear</span>();			<span class="comment">//移除容器的所有数据</span></span><br><span class="line"><span class="built_in">erase</span>(beg,end);		<span class="comment">//删除[beg,end)区间的数据，返回下一个数据的位置。</span></span><br><span class="line"><span class="built_in">erase</span>(pos);			<span class="comment">//删除pos位置的数据，返回下一个数据的位置。</span></span><br><span class="line"><span class="built_in">remove</span>(elem);		<span class="comment">//删除容器中所有与elem值匹配的元素。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="存、取-4"><a href="#存、取-4" class="headerlink" title="存、取"></a>存、取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">front</span>();	<span class="comment">//返回第一个元素。</span></span><br><span class="line"><span class="built_in">back</span>( );	<span class="comment">//返回最后一个元素。</span></span><br></pre></td></tr></table></figure></div>

<h3 id="反转和排序"><a href="#反转和排序" class="headerlink" title="反转和排序"></a>反转和排序</h3><hr>
<p>将容器中的元素反转，以及将容器中的数据进行排序。</p>
<p>&#x3D;&#x3D;所有不支持随机访问迭代器的容器，不可以用标准算法&#x3D;&#x3D;。</p>
<p>不支持随机访问迭代器的容器，内部会提供对应一些算法。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">reverse</span>(;	<span class="comment">//反转链表</span></span><br><span class="line"><span class="built_in">sort</span>();		<span class="comment">//链表排序，该函数是成员函数</span></span><br></pre></td></tr></table></figure></div>

<h2 id="pair对组"><a href="#pair对组" class="headerlink" title="pair对组"></a><code>pair</code>对组</h2><hr>
<p>对组指：成对出现的数据。利用对组可以使函数返回两个数据，对组嵌套对组时，可使函数返回多个数据。</p>
<h3 id="创建"><a href="#创建" class="headerlink" title="创建"></a>创建</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">pair&lt;type，type&gt; <span class="title">p</span> <span class="params">(value1, value2)</span></span>;</span><br><span class="line">pair&lt;type, type&gt; p = <span class="built_in">make_pair</span>(value1, value2);</span><br></pre></td></tr></table></figure></div>

<h3 id="数据获取"><a href="#数据获取" class="headerlink" title="数据获取"></a>数据获取</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">p.first; 	<span class="comment">//获取pair对象p的第一个数据</span></span><br><span class="line">p.second; 	<span class="comment">//获取pair对象p的第二个数据  </span></span><br></pre></td></tr></table></figure></div>

<h2 id="set容器和multiset容器"><a href="#set容器和multiset容器" class="headerlink" title="set容器和multiset容器"></a><code>set</code>容器和<code>multiset</code>容器</h2><hr>
<h3 id="基本概念-3"><a href="#基本概念-3" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<p>所有元素都会在插入时自动被排序。</p>
<p><code>set</code>和<code>multiset</code>属于关联式容器，底层结构是用二叉树实现。</p>
<p><code>set</code>和<code>multiset</code>区别：</p>
<ul>
<li><code>set</code>不允许容器中有重复的元素 </li>
<li><code>multiset</code>允许容器中有重复的元素</li>
</ul>
<h3 id="构造函数-7"><a href="#构造函数-7" class="headerlink" title="构造函数"></a>构造函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">set&lt;T&gt; st;				<span class="comment">//默认构造函数:</span></span><br><span class="line"><span class="built_in">set</span>(<span class="type">const</span> set &amp;st) ;	<span class="comment">//拷贝构造函数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="赋值-5"><a href="#赋值-5" class="headerlink" title="赋值"></a>赋值</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">set&amp; <span class="keyword">operator</span>=(<span class="type">const</span> set &amp;st);<span class="comment">//重载等号操作符</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除-4"><a href="#插入和删除-4" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">insert</span>(elem) ;		<span class="comment">//在容器中插入元素。</span></span><br><span class="line"><span class="built_in">clear</span>();			<span class="comment">//清除所有元素</span></span><br><span class="line"><span class="built_in">erase</span>(pos);			<span class="comment">//删除pos迭代器所指的元素，返回下一个元素的迭代器。</span></span><br><span class="line"><span class="built_in">erase</span>(beg，end);		<span class="comment">//删除区间[beg,end)的所有元素，返回下一个元素的迭代器。</span></span><br><span class="line"><span class="built_in">erase</span>(elem);		<span class="comment">//删除容器中值为elem的元素。</span></span><br></pre></td></tr></table></figure></div>

<p>对于<code>set</code>容器，因为不允许插入相同数据，因此插入函数返回值是一个<code>pair&lt;iterator,bool&gt;</code>的数据类型，可用于判断是否插入成功。</p>
<p>示例代码：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">set&lt;<span class="type">int</span>&gt; s;</span><br><span class="line">pair&lt;set&lt;<span class="type">int</span>&gt; : :iterator，<span class="type">bool</span>&gt;ret = s.<span class="built_in">insert</span>(<span class="number">10</span>);<span class="keyword">if</span> (ret.second) </span><br><span class="line">&#123;</span><br><span class="line">	cout &lt;&lt;<span class="string">&quot;插入成功!&quot;</span>&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> </span><br><span class="line">&#123;</span><br><span class="line">	cout &lt;&lt;<span class="string">&quot;插入失败!”&lt;&lt;endl;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure></div>

<h3 id="容器大小-4"><a href="#容器大小-4" class="headerlink" title="容器大小"></a>容器大小</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">size</span>( ) ;<span class="comment">//返回容器中元素的数目</span></span><br><span class="line"><span class="built_in">empty</span>();<span class="comment">//判断容器是否为空</span></span><br></pre></td></tr></table></figure></div>

<h3 id="交换-1"><a href="#交换-1" class="headerlink" title="交换"></a>交换</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">swap</span>(st);<span class="comment">//交换两个集合容器</span></span><br></pre></td></tr></table></figure></div>

<h3 id="查找"><a href="#查找" class="headerlink" title="查找"></a>查找</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">find</span>(key) ;		<span class="comment">//查找key是否存在,若存在，返回该键的元素的迭代器;若不存在，返回set.end(;</span></span><br><span class="line"><span class="built_in">count</span>(key);		<span class="comment">//统计key的元素个数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="自定义排序规则"><a href="#自定义排序规则" class="headerlink" title="自定义排序规则"></a>自定义排序规则</h3><hr>
<ul>
<li><p>方式1：</p>
<p>定义一个类，重载<code>operator()</code>运算符，定义比较函数，将类名作为<code>set</code>容器的第二个类型。同时，这也是传统写法。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyCompare</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="function"><span class="type">bool</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> <span class="type">const</span><span class="comment">//新C++标准必须添加const，旧标准可不添加</span></span></span><br><span class="line"><span class="function">	</span>&#123;</span><br><span class="line">		<span class="keyword">return</span> a &gt; b;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	set&lt;<span class="type">int</span>, MyCompare&gt; S1;</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">98</span>);</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">52</span>);</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">25</span>);</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">74</span>);</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">82</span>);</span><br><span class="line">	S1.<span class="built_in">insert</span>(<span class="number">78</span>);</span><br><span class="line">	<span class="keyword">for</span> (<span class="keyword">auto</span>&amp; i : S1) </span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; i &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>方式2：</p>
<p>定义一个<code>lambda</code>表达式，并使用<code>decltype</code>获取类型，或者配合<code>std::function</code>及<code>reinterpret_cast</code>使用，作为<code>set</code>容器的第二个类型。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">auto</span> f = [](<span class="type">int</span> a, <span class="type">int</span> b) -&gt;<span class="type">bool</span> &#123;<span class="keyword">return</span> a &gt; b; &#125;;</span><br><span class="line">	<span class="function">set&lt;<span class="type">int</span>, <span class="title">decltype</span><span class="params">(f)</span>&gt; <span class="title">S2</span><span class="params">(f)</span></span>;</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">98</span>);</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">52</span>);</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">25</span>);</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">74</span>);</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">82</span>);</span><br><span class="line">	S2.<span class="built_in">insert</span>(<span class="number">78</span>);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> (<span class="keyword">auto</span>&amp; i : S2) </span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; i &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>方式3：</p>
<p>可以直接定义一个函数，通过转换将函数指针转换为一个类指针，再解引用，作为<code>set</code>容器的第二个类型。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">myCompare</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a &gt; b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">auto</span> f = myCompare;</span><br><span class="line">    <span class="keyword">using</span> FuncPtr = <span class="built_in">bool</span>(*)(<span class="type">int</span>, <span class="type">int</span>);</span><br><span class="line">    set&lt;<span class="type">int</span>, std::function&lt;<span class="type">bool</span>(<span class="type">int</span>, <span class="type">int</span>)&gt;&gt; <span class="built_in">S</span>(<span class="built_in">reinterpret_cast</span>&lt;FuncPtr&amp;&gt;(f));<span class="comment">//需要包含头文件#include &lt;functional&gt;</span></span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">98</span>); </span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">52</span>);</span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">25</span>);</span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">74</span>);</span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">82</span>);</span><br><span class="line">    S.<span class="built_in">insert</span>(<span class="number">78</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span>&amp; i : S) </span><br><span class="line">    &#123;</span><br><span class="line">        cout &lt;&lt; i &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>这段代码定义了一个函数<code>myCompare</code>，它接受两个<code>int</code>类型的参数<code>a</code>和<code>b</code>，并返回一个<code>bool</code>类型的值。函数的作用是比较<code>a</code>和<code>b</code>的大小，如果<code>a</code>大于<code>b</code>，则返回<code>true</code>，否则返回<code>false</code>。</p>
<p>接下来，代码定义了一个变量<code>f</code>，它的类型是<code>myCompare</code>函数的指针。然后，使用<code>using</code>关键字定义了一个别名<code>FuncPtr</code>，它表示一个指向<code>bool</code>类型函数的指针，该函数接受两个<code>int</code>类型的参数。</p>
<p>最后，代码定义了一个<code>set</code>容器<code>S</code>，它的元素类型是<code>int</code>，比较函数类型是<code>std::function&lt;bool(int, int)&gt;</code>。</p>
<p>在构造<code>set</code>对象时，使用<code>reinterpret_cast</code>将<code>f</code>的类型转换为<code>FuncPtr&amp;</code>类型，并将其作为比较函数传递给<code>set</code>对象。这样，<code>set</code>容器就可以使用<code>myCompare</code>函数来比较元素的大小了。</p>
</li>
</ul>
<p>这三段代码的输出结果是一样的，都是按降序输出<code>set</code>容器中的元素。</p>
<p>输出结果：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">98</span><br><span class="line">82</span><br><span class="line">78</span><br><span class="line">74</span><br><span class="line">52</span><br><span class="line">25</span><br></pre></td></tr></table></figure></div>

<h2 id="map容器和multimap容器"><a href="#map容器和multimap容器" class="headerlink" title="map容器和multimap容器"></a><code>map</code>容器和<code>multimap</code>容器</h2><hr>
<p><code>map</code>中所有元素都是<code>pair</code></p>
<p><code>pair</code>中第一个元素为<code>key</code>(键值)，起到索引作用，第二个元素为<code>value</code>(实值)</p>
<p>所有元素都会根据元素的键值自动排</p>
<p><code>map/multimap</code>属于关联式容器，底层结构是用二叉树实现。</p>
<p>可以根据<code>key</code>值快速找到<code>value</code>值</p>
<p><code>map</code>不允许容器中有重复<code>key</code>值元素</p>
<p><code>multimap</code>允许容器中有重复<code>key</code>值元素</p>
<h3 id="构造和赋值函数"><a href="#构造和赋值函数" class="headerlink" title="构造和赋值函数"></a>构造和赋值函数</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">map&lt;T1, T2&gt; mp;			<span class="comment">//map默认构造函数:</span></span><br><span class="line"><span class="built_in">map</span>(<span class="type">const</span> map &amp;mp);		<span class="comment">//拷贝构造函数</span></span><br><span class="line"></span><br><span class="line">map&amp; <span class="keyword">operator</span>=(<span class="type">const</span> map &amp;mp);<span class="comment">//重载等号操作符</span></span><br></pre></td></tr></table></figure></div>

<h3 id="大小和交换"><a href="#大小和交换" class="headerlink" title="大小和交换"></a>大小和交换</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">size</span>();		<span class="comment">//返回容器中元素的数目</span></span><br><span class="line"><span class="built_in">empty</span>();	<span class="comment">//判断容器是否为空</span></span><br><span class="line"><span class="built_in">swap</span>(st);	<span class="comment">//交换两个集合容器</span></span><br></pre></td></tr></table></figure></div>

<h3 id="插入和删除-5"><a href="#插入和删除-5" class="headerlink" title="插入和删除"></a>插入和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">insert</span>(elem) ;		<span class="comment">//在容器中插入元素。</span></span><br><span class="line"><span class="built_in">clear</span>();			<span class="comment">//清除所有元素</span></span><br><span class="line"><span class="built_in">erase</span>(pos);			<span class="comment">//删除pos迭代器所指的元素，返回下一个元素的迭代器。</span></span><br><span class="line"><span class="built_in">erase</span>(beg,end) ;	<span class="comment">//删除区间[beg,end)的所有元素，返回下一个元素的迭代器。</span></span><br><span class="line"><span class="built_in">erase</span>(key);		<span class="comment">//删除容器中值为key的元素。</span></span><br></pre></td></tr></table></figure></div>

<p>插入方式示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">map&lt;<span class="type">int</span>,<span class="type">int</span>&gt; m;</span><br><span class="line"><span class="comment">//插入</span></span><br><span class="line"><span class="comment">//第一种</span></span><br><span class="line">m.<span class="built_in">insert</span>(<span class="built_in">pair</span>&lt;<span class="type">int</span>,<span class="type">int</span>&gt;(<span class="number">1</span>, <span class="number">10</span>));</span><br><span class="line"><span class="comment">//第二种</span></span><br><span class="line">m.<span class="built_in">insert</span>(<span class="built_in">make_pair</span>(<span class="number">2</span>, <span class="number">20</span>));</span><br><span class="line"><span class="comment">//第三种</span></span><br><span class="line">m.<span class="built_in">insert</span>(map&lt;<span class="type">int</span>，<span class="type">int</span>&gt;::<span class="built_in">value_type</span>(<span class="number">3</span>, <span class="number">30</span>));</span><br><span class="line"><span class="comment">//第四种</span></span><br><span class="line">m[<span class="number">4</span>] = <span class="number">40</span>;</span><br></pre></td></tr></table></figure></div>

<h3 id="查找和删除"><a href="#查找和删除" class="headerlink" title="查找和删除"></a>查找和删除</h3><hr>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">find</span>(key); 		<span class="comment">//查找key是否存在,若存在，返回该键的元素的迭代器;若不存在，返回set.end();</span></span><br><span class="line"><span class="built_in">count</span>(key);		<span class="comment">//统计key的元素个数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="自定义排序"><a href="#自定义排序" class="headerlink" title="自定义排序"></a>自定义排序</h3><hr>
<p>同<code>set</code>容器，定义一个仿函数或<code>lambda</code>和函数通过转换后，作为模板参数列表的第三个参数。</p>
<h2 id="函数对象"><a href="#函数对象" class="headerlink" title="函数对象"></a>函数对象</h2><hr>
<h3 id="基本概念-4"><a href="#基本概念-4" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<ul>
<li><p>重载函数调用操作符的类，其对象常称为函数对象。</p>
</li>
<li><p>函数对象使用重载的()时，行为类似函数调用，也叫仿函数。</p>
</li>
<li><p>函数对象(仿函数)的本质是一个类，不是一个函数。</p>
</li>
</ul>
<h3 id="函数对象的使用"><a href="#函数对象的使用" class="headerlink" title="函数对象的使用"></a>函数对象的使用</h3><hr>
<p>函数对象在使用时，可以像普通函数那样调用，可以有参数，可以有返回值，函数对象超出普通函数的概念。</p>
<p>函数对象可以有自己的状态（类成员），这叫做”闭包“，也叫“上下文关联的函数”。</p>
<p>函数对象可以作为参数传递。</p>
<h2 id="谓词（predicate）的概念"><a href="#谓词（predicate）的概念" class="headerlink" title="谓词（predicate）的概念"></a>谓词（predicate）的概念</h2><hr>
<p>在编程中，谓词（Predicate）是指用于判断某个条件是否为真的函数或表达式。</p>
<p>谓词通常返回一个布尔值（True或False），表示某种断言的真假。</p>
<p>在各种编程语言和环境中，谓词都扮演着重要的角色，用于条件判断、过滤、排序、搜索等各种操作。</p>
<p>谓词的概念在逻辑学中也很常见，用于描述命题的真值。</p>
<p>在编程中，谓词是对逻辑思维的一种抽象，让我们能够将复杂的条件逻辑转换为可执行的代码。</p>
<p>在C++中，谓词可以是以下几种形式：</p>
<ul>
<li><p>函数谓词：一个函数，接受一个或多个参数，并返回布尔值。</p>
<p>通过调用该函数并传入相应参数，可以判断特定条件是否为真。</p>
<p>例如，使用一个函数谓词来判断一个数是否是偶数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数谓词：判断一个数是否是偶数</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">is_even</span><span class="params">(<span class="type">int</span> number)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> number % <span class="number">2</span> == <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 使用谓词函数判断一个数是否为偶数</span></span><br><span class="line">    <span class="type">bool</span> result = <span class="built_in">is_even</span>(<span class="number">10</span>);</span><br><span class="line">    std::cout &lt;&lt; std::boolalpha &lt;&lt; result &lt;&lt; std::endl;  <span class="comment">// 输出: true</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这段代码中，定义了一个函数谓词 <code>is_even</code> 来判断一个数是否是偶数。</p>
<p>然后，在 <code>main</code> 函数中使用该谓词来判断整数 <code>10</code> 是否为偶数，并将结果打印出来。</p>
<p>并通过 <code>std::boolalpha</code> 操纵符来让输出以布尔值形式显示。</p>
<p>在C++中，谓词通常是用于判断条件是否为真的函数或函数对象（仿函数）。</p>
<p>谓词的主要特点是它返回<code>bool</code>类型的结果，用于条件判断。</p>
<ul>
<li><p>返回<code>bool</code>类型的仿函数也称为谓词。在C++中，谓词通常是一种函数对象（仿函数），它可以是普通函数、Lambda表达式或重载了函数调用运算符<code>operator()</code>的类对象。</p>
</li>
<li><p>如果<code>operator()</code>接受一个参数，那么谓词被称为一元谓词。一元谓词用于对单个元素进行条件判断。</p>
</li>
<li><p>如果<code>operator()</code>接受两个参数，那么谓词被称为二元谓词。二元谓词用于对两个元素进行条件判断，例如在排序算法中用于定义排序顺序。</p>
<p>以此类推……</p>
</li>
</ul>
</li>
<li><p>lambda 表达式谓词：一种匿名函数，通常用于简单的条件判断或过滤操作。</p>
<p>&#x3D;&#x3D;（关于lambda表达式将在以后学习，这里可不做了解，直接跳过即可）&#x3D;&#x3D;</p>
<p>例如，使用lambda表达式谓词来筛选出列表中的偶数：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::vector&lt;<span class="type">int</span>&gt; numbers = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>&#125;;</span><br><span class="line">    std::vector&lt;<span class="type">int</span>&gt; even_numbers;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用Lambda表达式谓词来筛选出列表中的偶数</span></span><br><span class="line">    std::<span class="built_in">copy_if</span>(numbers.<span class="built_in">begin</span>(), numbers.<span class="built_in">end</span>(), std::<span class="built_in">back_inserter</span>(even_numbers),</span><br><span class="line">                 [](<span class="type">int</span> x) &#123; <span class="keyword">return</span> x % <span class="number">2</span> == <span class="number">0</span>; &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 输出筛选结果</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> num : even_numbers) </span><br><span class="line">    &#123;</span><br><span class="line">        std::cout &lt;&lt; num &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    std::cout &lt;&lt; std::endl;  <span class="comment">// 输出: 2 4 6</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
</li>
<li><p>逻辑表达式谓词：通过逻辑运算符（如AND、OR、NOT）将多个条件组合成一个复合条件。</p>
<p>例如，使用逻辑表达式谓词判断一个数是否在某个范围内：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">is_in_range</span><span class="params">(<span class="type">int</span> number)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (number &gt;= <span class="number">10</span>) &amp;&amp; (number &lt;= <span class="number">20</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 使用谓词函数判断一个数是否在特定范围内</span></span><br><span class="line"><span class="type">bool</span> result = <span class="built_in">is_in_range</span>(<span class="number">15</span>);</span><br><span class="line">cout &lt;&lt; result &lt;&lt; endl;  <span class="comment">// 输出: 1 (True)</span></span><br></pre></td></tr></table></figure></div></li>
</ul>
<p>在STL（标准模板库）中，谓词广泛应用于各种算法函数，如<code>std::find_if</code>、<code>std::sort</code>、<code>std::remove_if</code>等。</p>
<p>它们允许我们根据自定义的条件对容器中的元素进行过滤、排序、搜索等操作，提高了代码的灵活性和可复用性。</p>
<p>谓词的使用在STL和现代C++编程中非常常见。</p>
<h2 id="STL的内建函数对象"><a href="#STL的内建函数对象" class="headerlink" title="STL的内建函数对象"></a>STL的内建函数对象</h2><hr>
<h3 id="基本概念-5"><a href="#基本概念-5" class="headerlink" title="基本概念"></a>基本概念</h3><hr>
<p>STL（Standard Template Library）的内建函数对象（Builtin Function Objects）是一组在C++标准库中提供的用于函数对象操作的预定义类模板。</p>
<p>函数对象是类对象，其行为类似于函数，可以像函数一样被调用。</p>
<p>这些内建函数对象封装了常见的操作，如算术运算、逻辑运算、比较运算等，可以在各种算法和容器操作中使用。</p>
<p>STL内建函数对象的概念主要包括以下几个方面：</p>
<ul>
<li><p>仿函数（Function Object）：</p>
<p>STL的内建函数对象通常被称为仿函数，因为它们是函数对象的模拟，具有函数调用运算符<code>operator()</code>，可以像函数一样被调用。</p>
<p>STL提供了一些预定义的仿函数类模板，同时也可以自定义自己的仿函数。</p>
</li>
<li><p>预定义的函数对象：</p>
<p>STL标准库中预定义了一些常用的函数对象类模板，这些函数对象用于执行各种操作，如加法、减法、乘法、除法、逻辑与、逻辑或、比较等。</p>
</li>
<li><p>函数对象适用于算法：</p>
<p>STL中的算法往往接受函数对象作为参数，这样就可以在执行算法时，通过函数对象来定义特定的操作逻辑。</p>
<p>例如，<code>std::transform</code>、<code>std::sort</code>、<code>std::find_if</code>等算法都接受函数对象，从而允许我们以不同的方式处理元素。</p>
</li>
</ul>
<p>STL内建函数对象的使用使得编写更加通用和灵活的代码变得更加容易。</p>
<p>通过使用预定义的函数对象，我们可以避免重复编写某些常见的操作逻辑，并且提高代码的可读性和可维护性。</p>
<p>此外，STL内建函数对象也为编写泛型代码提供了强大的工具，使得算法和容器操作可以适用于不同类型的数据。</p>
<p>STL内建的一些函数对象的分类：</p>
<ul>
<li>算术仿函数</li>
<li>关系仿函</li>
<li>逻辑仿函数</li>
</ul>
<p>等等……</p>
<p>这些仿函数所产生的对象，用法和一般函数完全相同，使用内建函数对象，需要包含头文件<code>#include&lt;functional&gt;</code></p>
<h3 id="算数仿函数"><a href="#算数仿函数" class="headerlink" title="算数仿函数"></a>算数仿函数</h3><hr>
<p>作用：实现四则运算</p>
<p>其中&#96;&#96;negate&#96;是一元运算，其他都是二元运算仿函数</p>
<p>模板原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T plus&lt;T&gt;			<span class="comment">//加法仿函数</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T minus&lt;T&gt;		<span class="comment">//减法仿函数</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T multiplies&lt;T&gt;	<span class="comment">//乘法仿函数</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T divides&lt;T&gt;		<span class="comment">//除法仿函数</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T modulus&lt;T&gt;		<span class="comment">//取模仿函数</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; T negate&lt;T&gt;		<span class="comment">//取反仿函数</span></span><br></pre></td></tr></table></figure></div>

<h3 id="关系仿函数"><a href="#关系仿函数" class="headerlink" title="关系仿函数"></a>关系仿函数</h3><hr>
<p>功能描述：实现关系对比</p>
<p>模板原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> equal_to&lt;T&gt;		<span class="comment">//等于</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> not_equal_to&lt;T&gt;	<span class="comment">//不等于</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> greater&lt;T&gt;		<span class="comment">//大于</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> greater_equal&lt;T&gt;	<span class="comment">//大于等于</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> less&lt;T&gt;			<span class="comment">//小于</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> less_equal&lt;T&gt;	<span class="comment">//小于等于</span></span><br></pre></td></tr></table></figure></div>

<h3 id="逻辑仿函数"><a href="#逻辑仿函数" class="headerlink" title="逻辑仿函数"></a>逻辑仿函数</h3><hr>
<p>功能：实现逻辑运算</p>
<p>模板原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> logical_and&lt;T&gt;	<span class="comment">//逻辑与</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> logical_or&lt;T&gt;	<span class="comment">//逻辑或</span></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">class</span> <span class="title class_">T</span>&gt; <span class="type">bool</span> logical_not&lt;T&gt;	<span class="comment">//逻辑非</span></span><br></pre></td></tr></table></figure></div>

<h2 id="STL常用算法"><a href="#STL常用算法" class="headerlink" title="STL常用算法"></a>STL常用算法</h2><hr>
<h3 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h3><hr>
<p>算法主要是由头文件<code>&lt;algorithm&gt;</code>、<code>&lt;functional&gt;</code>、<code> &lt;numeric&gt;</code>组成。</p>
<ul>
<li><p><code>&lt;algorithm&gt;</code>是所有<code>STL</code>头文件中最大的一个，范围涉及到比较、交换、查找、遍历操作、复制、修改等等</p>
</li>
<li><p><code>&lt;numeric&gt;</code>体积很小，只包括几个在序列上面进行简单数学运算的模板函数</p>
</li>
<li><p><code>&lt;functional&gt;</code>定义了一些模板类,用以声明函数对象。</p>
</li>
</ul>
<h3 id="常用遍历算法"><a href="#常用遍历算法" class="headerlink" title="常用遍历算法"></a>常用遍历算法</h3><hr>
<h4 id="for-each遍历"><a href="#for-each遍历" class="headerlink" title="for_each遍历"></a><code>for_each</code>遍历</h4><hr>
<p>功能描述：实现遍历容器</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for_each(iterator beg, iterator end, _func );<span class="comment">//遍历算法遍历容器元素</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// _func函数或者函数对象</span></span><br></pre></td></tr></table></figure></div>

<h3 id="常用查找算法"><a href="#常用查找算法" class="headerlink" title="常用查找算法"></a>常用查找算法</h3><hr>
<h4 id="find-查找"><a href="#find-查找" class="headerlink" title="find 查找"></a><code>find</code> 查找</h4><hr>
<p>功能：查找指定元素，找到返回指定元素的迭代器，找不到返回结束迭代器<code>end()</code>。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">find</span>(iterator beg, iteratbr end, value) ;<span class="comment">//按值查找元素，找到返回指定位置迭代器，找不到返回结束迭代器位置</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// value查找的元素</span></span><br></pre></td></tr></table></figure></div>

<p>注意！查找自定义数据类型，需要重载<code>operator==</code>。</p>
<h4 id="find-if按条件查找"><a href="#find-if按条件查找" class="headerlink" title="find_if按条件查找"></a><code>find_if</code>按条件查找</h4><hr>
<p>功能：按条件查找元素函数。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">find_if</span>(iterator beg, iterator end，_Pred);<span class="comment">//按值查找元素，找到返回指定位置迭代器，找不到返回结束迭代器位置</span></span><br><span class="line"><span class="comment">// beg 开始迭代器</span></span><br><span class="line"><span class="comment">//end结束迭代器</span></span><br><span class="line"><span class="comment">//_Pred函数或者谓词(返回bool类型的仿函数)</span></span><br></pre></td></tr></table></figure></div>

<h4 id="adjacent-find查找相邻重复元素"><a href="#adjacent-find查找相邻重复元素" class="headerlink" title="adjacent_find查找相邻重复元素"></a><code>adjacent_find</code>查找相邻重复元素</h4><hr>
<p>功能：查找相邻重复元素。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">adjacent_find</span>(iterator beg， iterator end ) ;<span class="comment">//查找相邻重复元素,返回相邻元素的第一个位置的迭代器</span></span><br><span class="line"><span class="comment">//beg 开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br></pre></td></tr></table></figure></div>

<h4 id="binary-search二分查找"><a href="#binary-search二分查找" class="headerlink" title="binary_search二分查找"></a><code>binary_search</code>二分查找</h4><hr>
<p>功能：查找指定元素是否存在。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">binary_search</span><span class="params">(iterator beg, iterator end, value)</span></span>;<span class="comment">//查找指定的元素，查到返回true否则false</span></span><br><span class="line"><span class="comment">// beg 开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// value查找的元素</span></span><br></pre></td></tr></table></figure></div>

<p>注意！查找的容器或数组必须已经排好序的（有序序列），在无序序列中不可用。</p>
<h3 id="常用统计算法"><a href="#常用统计算法" class="headerlink" title="常用统计算法"></a>常用统计算法</h3><h4 id="count统计个数"><a href="#count统计个数" class="headerlink" title="count统计个数"></a><code>count</code>统计个数</h4><hr>
<p>功能：统计相同元素个数。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">count</span>( iterator beg, iterator end，valle);<span class="comment">//统计元素出现次数</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// value统计的元素</span></span><br></pre></td></tr></table></figure></div>

<p>对于自定义数据类型，需要重载<code>operator==</code>。</p>
<h4 id="count-if按条件统计个数"><a href="#count-if按条件统计个数" class="headerlink" title="count_if按条件统计个数"></a><code>count_if</code>按条件统计个数</h4><hr>
<p>功能：按条件统计元素个数</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">count_if</span>(iterator beg, iterator end，_pred ) ;<span class="comment">//按条件统计元素出现次数</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// _Pred谓词</span></span><br></pre></td></tr></table></figure></div>

<h3 id="常用排序算法"><a href="#常用排序算法" class="headerlink" title="常用排序算法"></a>常用排序算法</h3><h4 id="sort排序"><a href="#sort排序" class="headerlink" title="sort排序"></a><code>sort</code>排序</h4><hr>
<p>功能：对容器内元素进行排序。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sort</span>(iterator beg, iterator end, _Pred);<span class="comment">//按值查找元素，找到返回指定位置迭代器，找不到返回结束迭代器位置</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// _Pred 谓词</span></span><br></pre></td></tr></table></figure></div>

<p>谓词参数可不指定。不指定则默认升序排序</p>
<h4 id="random-shuffle随机排序"><a href="#random-shuffle随机排序" class="headerlink" title="random_shuffle随机排序"></a><code>random_shuffle</code>随机排序</h4><hr>
<p>功能：对容器内元素进行随机排序，打乱原有序列。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">random_shuffle</span>(iterator beg, iterator end ) ;<span class="comment">//指定范围内的元素随机调整次序</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！需要指定随机数种子，才能使每次排序顺序都不一样。</p>
<h3 id="常用拷贝和替换算法"><a href="#常用拷贝和替换算法" class="headerlink" title="常用拷贝和替换算法"></a>常用拷贝和替换算法</h3><hr>
<h4 id="copy复制"><a href="#copy复制" class="headerlink" title="copy复制"></a><code>copy</code>复制</h4><hr>
<p>功能：将容器内指定范围的元素拷贝到另—容器中。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">copy</span>(iterator beg， iterator end，iterator dest;<span class="comment">//按值查找元素，找到返回指定位置迭代器，找不到返回结束迭代器位置ll beg开始迭代器</span></span><br><span class="line"><span class="comment">// end 结束迭代器</span></span><br><span class="line"><span class="comment">// dest目标起始迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！目标容器需要提前开辟空间。</p>
<h4 id="transform搬运容器"><a href="#transform搬运容器" class="headerlink" title="transform搬运容器"></a><code>transform</code>搬运容器</h4><hr>
<p>功能描述：搬运容器到另个容器中</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">transform</span>(iterator beg1, iterator end1, iterator beg2, _func);<span class="comment">//beg1源容器开始迭代器</span></span><br><span class="line"><span class="comment">//end1源容器结束迭代器</span></span><br><span class="line"><span class="comment">//beg2目标容器开始迭代器</span></span><br><span class="line"><span class="comment">//_func函数或者函数对象</span></span><br></pre></td></tr></table></figure></div>

<p>注意！目标容器需要提前开辟空间。</p>
<h4 id="replace替换"><a href="#replace替换" class="headerlink" title="replace替换"></a><code>replace</code>替换</h4><hr>
<p>功能：将容器内指定范围的旧元素修改为新元素。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">replace</span>(iterator beg, iterator end,oldvalue，newvalue) ;<span class="comment">//将区间内旧元素替换成新元素</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// oldvalue 旧元素</span></span><br><span class="line"><span class="comment">// newvalue 新元素</span></span><br></pre></td></tr></table></figure></div>

<h4 id="replace-if按条件替换"><a href="#replace-if按条件替换" class="headerlink" title="replace_if按条件替换"></a><code>replace_if</code>按条件替换</h4><hr>
<p>功能：将区间内满足条件的元素，替换成指定元素。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">replace_if</span>(iterator beg, iterator end, _pred, newvalue);<span class="comment">//按条件替换元素，满足条件的替换成指定元素</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">//_pred谓词</span></span><br><span class="line"><span class="comment">// newvalue替换的新元素</span></span><br></pre></td></tr></table></figure></div>

<h4 id="swap交换"><a href="#swap交换" class="headerlink" title="swap交换"></a><code>swap</code>交换</h4><hr>
<p>功能：互换两个容器的元素。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">swap</span>(container c1,container c2);<span class="comment">//互换两个容器的元素</span></span><br><span class="line"><span class="comment">// c1容器1</span></span><br><span class="line"><span class="comment">// c2容器2</span></span><br></pre></td></tr></table></figure></div>

<h3 id="常用算术生成算法"><a href="#常用算术生成算法" class="headerlink" title="常用算术生成算法"></a>常用算术生成算法</h3><hr>
<p>算术生成算法属于小型算法，使用时包含的头文件为<code>#include &lt;numeric&gt;</code>。</p>
<h4 id="accumulate累加"><a href="#accumulate累加" class="headerlink" title="accumulate累加"></a><code>accumulate</code>累加</h4><hr>
<p>功能：计算区间内容器元素累计总和。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">accumulate</span>(iterator beg, iterator end, value) ;<span class="comment">//计算容器元素累计总和</span></span><br><span class="line"><span class="comment">// beg 开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// value起始累加值</span></span><br></pre></td></tr></table></figure></div>

<h4 id="fill填充"><a href="#fill填充" class="headerlink" title="fill填充"></a><code>fill</code>填充</h4><hr>
<p>功能：向容器中填充指定的元素。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">fill</span>(iterator beg, iterator end,value);<span class="comment">//向容器中填充元素</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br><span class="line"><span class="comment">// value填充的值</span></span><br></pre></td></tr></table></figure></div>

<p>注意！目标容器需要提前开辟空间。</p>
<h3 id="常用集合算法"><a href="#常用集合算法" class="headerlink" title="常用集合算法"></a>常用集合算法</h3><hr>
<h4 id="set-intersection求交集"><a href="#set-intersection求交集" class="headerlink" title="set_intersection求交集"></a><code>set_intersection</code>求交集</h4><hr>
<p>功能：求两个容器的交集。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set_intersection</span>(iterator beg1，iterator end1，iterator beg2，iterator end2，iterator dest);<span class="comment">//求两个集合的交集</span></span><br><span class="line"><span class="comment">// beg1容器1开始迭代器</span></span><br><span class="line"><span class="comment">// end1容器1结束迭代器</span></span><br><span class="line"><span class="comment">// beg2容器2开始迭代器</span></span><br><span class="line"><span class="comment">// end2容器2结束迭代器</span></span><br><span class="line"><span class="comment">// dest目标容器开始迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！</p>
<ul>
<li>目标容器需要提前开辟空间。最特殊情况大容器包含小容器开辟空间取小容器的size即可。</li>
<li>返回值为一个迭代器，指向交集的最后一个元素。之后可通过该迭代器重新指定容器大小。</li>
<li>两个集合必须是有序序列。</li>
</ul>
<h4 id="set-unionl求并集"><a href="#set-unionl求并集" class="headerlink" title="set_unionl求并集"></a><code>set_unionl</code>求并集</h4><hr>
<p>功能：求两个容器的并集。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set_union</span>(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);<span class="comment">//求两个集合的并集</span></span><br><span class="line"><span class="comment">// beg1容器1开始迭代霸</span></span><br><span class="line"><span class="comment">// end1容器1结束迭代器</span></span><br><span class="line"><span class="comment">// beg2容器2开始迭代器</span></span><br><span class="line"><span class="comment">// end2容器2结束迭代器</span></span><br><span class="line"><span class="comment">// dest目标容器开始迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！</p>
<ul>
<li>目标容器需要提前开辟空间。最特殊情况两个容器没有公共元素，开辟空间大小取两个容器size和即可。</li>
<li>返回值为一个迭代器，指向并集的最后一个元素。之后可通过该迭代器重新指定容器大小。</li>
<li>两个集合必须是有序序列。</li>
</ul>
<h4 id="set-difference求差集"><a href="#set-difference求差集" class="headerlink" title="set_difference求差集"></a><code>set_difference</code>求差集</h4><hr>
<p>功能：求两个容器的差集。</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set_difference</span>(iterator beg1, iterator end1 ,iterator beg2, iterator end2, iterator dest);<span class="comment">//求两个集合的差集</span></span><br><span class="line"><span class="comment">// beg1容器1开始迭代器</span></span><br><span class="line"><span class="comment">// end1容器1结束迭代器</span></span><br><span class="line"><span class="comment">// beg2容器2开始迭代器</span></span><br><span class="line"><span class="comment">// end2容器2结束迭代器</span></span><br><span class="line"><span class="comment">// dest目标容器开始迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！</p>
<ul>
<li>目标容器需要提前开辟空间。最特殊情况，两个容器没有交集，取第一个容器的size即可（也可取两个容器中较大的size作为目标容器开辟空间）</li>
<li>返回值为一个迭代器，指向差集的最后一个元素。之后可通过该迭代器重新指定容器大小。</li>
<li>两个集合必须是有序序列。</li>
</ul>
<h3 id="其他常用算法"><a href="#其他常用算法" class="headerlink" title="其他常用算法"></a>其他常用算法</h3><hr>
<h4 id="merge合并容器"><a href="#merge合并容器" class="headerlink" title="merge合并容器"></a><code>merge</code>合并容器</h4><hr>
<p>功能：将两个容器元素合并，并存储到另—容器中</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">merge</span>(iterator beg1，iterator end1， iterator beg2，iterator end2，iterator dest);<span class="comment">//容器元素合并，并存储到另一容器中</span></span><br><span class="line"><span class="comment">// beg1容器1开始迭代器</span></span><br><span class="line"><span class="comment">// end1容器1结束迭代器</span></span><br><span class="line"><span class="comment">// beg2容器2开始迭代器</span></span><br><span class="line"><span class="comment">// end2容器2结束迭代器</span></span><br><span class="line"><span class="comment">// dest目标容器开始迭代器</span></span><br></pre></td></tr></table></figure></div>

<p>注意！原始的两个容器必须是有序的且必须是一致的顺序（同为升序或降序）。</p>
<h4 id="reverse"><a href="#reverse" class="headerlink" title="reverse"></a><code>reverse</code></h4><hr>
<p>功能：将容器内元素进行反转</p>
<p>函数原型：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">reverse</span>(iterator beg，iterator end);<span class="comment">//反转指定范围的元素</span></span><br><span class="line"><span class="comment">// beg开始迭代器</span></span><br><span class="line"><span class="comment">// end结束迭代器</span></span><br></pre></td></tr></table></figure></div>

<p><a class="link"   target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1z24y1b7LZ?vd_source=03da7de0e80f9ff60fdeca7b512ba3f5" >https://www.bilibili.com/video/BV1z24y1b7LZ?vd_source=03da7de0e80f9ff60fdeca7b512ba3f5 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a>)</p>
<h1 id="C-文件操作"><a href="#C-文件操作" class="headerlink" title="C++文件操作"></a>C++文件操作</h1><h2 id="概述-1"><a href="#概述-1" class="headerlink" title="概述"></a>概述</h2><hr>
<p>C++中对文件操作需要包含头文件<code>#include &lt;fstream&gt;</code></p>
<p>文件类型分为两种:</p>
<ul>
<li>文本文件-文件以文本的ASCII码形式存储在计算机中</li>
<li>二进制文件-文件以文本的二进制形式存储在计算机中，用户一般不能直接读懂它们</li>
</ul>
<p>操作文件的三大类:</p>
<ul>
<li><code>ofstream</code>：写操作</li>
<li><code>ifstream</code>：读操作</li>
<li><code>fstream</code>：读写操作</li>
</ul>
<p>文件操作的一般步骤：</p>
<ul>
<li><p>包含头文件<code>#include &lt;fstream&gt;</code></p>
</li>
<li><p>根据读写需要创建对应的流对象</p>
</li>
<li><p>打开文件时要判断文件是否打开成功</p>
<p>对于写入数据，如果文件打开失败一般会创建一个新文件，因此可能总是打开成功的。</p>
</li>
<li><p>读取或写入</p>
</li>
<li><p>关闭文件调用</p>
<p>当程序终止时，系统会自动关闭刷新所有流，释放所有分配的内存，并关闭所有打开的文件。</p>
<p>但程序员应该养成一个好习惯，在程序终止前关闭所有打开的文件。</p>
</li>
</ul>
<h2 id="文件的打开方式"><a href="#文件的打开方式" class="headerlink" title="文件的打开方式"></a>文件的打开方式</h2><hr>
<p>在对一个文件进行读或写之前需要将这个文件打开，因此有了打开方式这一说法。</p>
<p>打开方式：</p>
<table>
<thead>
<tr>
<th align="left">打开方式</th>
<th align="left">解释</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>ios::in</code></td>
<td align="left">打开文件用于读取</td>
</tr>
<tr>
<td align="left"><code>ios::out</code></td>
<td align="left">打开文件用于写入</td>
</tr>
<tr>
<td align="left"><code>ios::ate	</code></td>
<td align="left">打开文件后的初始位置：文件尾</td>
</tr>
<tr>
<td align="left"><code>ios::app</code></td>
<td align="left">追加模式，所有写入都追加到文件末尾。</td>
</tr>
<tr>
<td align="left"><code>ios::trunc</code></td>
<td align="left">如果文件存在先删除，再创建（覆写）</td>
</tr>
<tr>
<td align="left"><code>ios::binary</code></td>
<td align="left">二进制方式</td>
</tr>
</tbody></table>
<p>注意：</p>
<ul>
<li><p>文件打开方式可以配合使用，利用<code>|</code> 操作符。</p>
<p>例如：用二进制方式写文件<code>ios::binary | ios::out</code></p>
</li>
</ul>
<h2 id="文本文件"><a href="#文本文件" class="headerlink" title="文本文件"></a>文本文件</h2><hr>
<h3 id="写文件"><a href="#写文件" class="headerlink" title="写文件"></a>写文件</h3><hr>
<p>写文件步骤如下：</p>
<ul>
<li><p>包含头文件：<code>#include &lt;fstream&gt;</code></p>
</li>
<li><p>创建流对象：<code>ofstream ofs</code></p>
</li>
<li><p>打开文件</p>
<p>指定文件路径和打开方式：<code>ofs.open(&quot;文件路径&quot;, 打开方式式)</code></p>
</li>
<li><p>写数据：<code>ofs &lt;&lt;&quot;写入的数据&quot;</code></p>
</li>
<li><p>关闭文件：<code>ofs.close()</code></p>
</li>
</ul>
<p>示例（写入一个文本文件）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fstream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    ofstream ofs;<span class="comment">//创建流对象</span></span><br><span class="line">	ofs.<span class="built_in">open</span>(<span class="string">&quot;test.txt&quot;</span>, ios::out);<span class="comment">//指定打开文件路径和打开方式</span></span><br><span class="line">	ofs &lt;&lt; <span class="string">&quot;Hello world&quot;</span> &lt;&lt; endl;<span class="comment">//写入 Hello world 并换行</span></span><br><span class="line">    ofs &lt;&lt; <span class="string">&quot;Hello C++&quot;</span>&lt;&lt; endl;<span class="comment">//写入 Hello C++ 并换行</span></span><br><span class="line">	ofs.<span class="built_in">close</span>();<span class="comment">//关闭文件</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>要点总结</p>
<ul>
<li><p>文件操作必须包含头文件<code>fstream</code></p>
</li>
<li><p>读文件可以利用<code>ofstream</code> ，或者<code>fstream</code>类</p>
</li>
<li><p>打开文件时候需要指定操作文件的路径，以及打开方式。</p>
</li>
<li><p>利用<code>&lt;&lt;</code>以向文件中写数据</p>
</li>
<li><p>操作完毕，要关闭文件</p>
</li>
</ul>
<h3 id="读文件"><a href="#读文件" class="headerlink" title="读文件"></a>读文件</h3><hr>
<p>读文件步骤如下:</p>
<ul>
<li>包含头文件<code>#include &lt;fstream&gt;</code></li>
<li>创建流对象<code>ifstream ifs</code></li>
<li>打开文件并判断文件是否打开成功<code>ifs.open(&quot;文件路径&quot;,打开方式)</code></li>
<li>读数据：四种方式读取</li>
<li>关闭文件<code>ifs.close()</code>;</li>
</ul>
<p>读数据四种方式：</p>
<ul>
<li>第一种，将文件中的内容全部放到字符数组中，注意：数组大小必须&gt;&#x3D;文件内容的字符数量，否则程序崩溃</li>
<li>第二种，将文件中的内容一行一行的写入字符数组中，并根据数组大小，写入相应大小的内容</li>
<li>第三种，将文件中的内容写入string字符串中</li>
<li>第四种，将文件中的内容一个一个的读取并写入到一个<code>char</code>字符中，一个一个的输出，效率低</li>
</ul>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//读数据，四种方式</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">read1</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	ifstream ifs;<span class="comment">//创建流对象</span></span><br><span class="line">	ifs.<span class="built_in">open</span>(<span class="string">&quot;test.txt&quot;</span>, ios::in);<span class="comment">//打开文件并</span></span><br><span class="line">	<span class="keyword">if</span>(!ifs.<span class="built_in">is_open</span>())<span class="comment">//判断文件是否打开成功</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;文件打开失败&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;		</span><br><span class="line">	<span class="comment">//读数据</span></span><br><span class="line">		<span class="comment">//第一种，将文件中的内容全部放到字符数组中，注意：数组大小必须&gt;=文件内容的字符数量，否则程序崩溃</span></span><br><span class="line">	<span class="type">char</span> buf[<span class="number">1024</span>] = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	<span class="keyword">while</span> (ifs &gt;&gt; buf)</span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; buf ;</span><br><span class="line">	&#125;</span><br><span class="line">	cout &lt;&lt; endl;</span><br><span class="line">	ifs.<span class="built_in">close</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">read2</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	ifstream ifs;<span class="comment">//创建流对象</span></span><br><span class="line">	ifs.<span class="built_in">open</span>(<span class="string">&quot;test.txt&quot;</span>, ios::in);<span class="comment">//打开文件并</span></span><br><span class="line">	<span class="keyword">if</span> (!ifs.<span class="built_in">is_open</span>())<span class="comment">//判断文件是否打开成功</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;文件打开失败&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">//读数据</span></span><br><span class="line">		<span class="comment">//第二种，将文件中的内容一行一行的写入字符数组中，并根据数组大小，写入相应大小的内容</span></span><br><span class="line">	<span class="type">char</span> buf[<span class="number">1024</span>] = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	<span class="keyword">while</span> (ifs.<span class="built_in">getline</span>(buf, <span class="built_in">sizeof</span>(buf)))<span class="comment">//ifs下的getline()函数，参数一：数组首地址，参数二：数组大小</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; buf &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	ifs.<span class="built_in">close</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">read3</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	ifstream ifs;<span class="comment">//创建流对象</span></span><br><span class="line">	ifs.<span class="built_in">open</span>(<span class="string">&quot;test.txt&quot;</span>, ios::in);<span class="comment">//打开文件并</span></span><br><span class="line">	<span class="keyword">if</span> (!ifs.<span class="built_in">is_open</span>())<span class="comment">//判断文件是否打开成功</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;文件打开失败&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">//读数据</span></span><br><span class="line">		<span class="comment">//第三种，将文件中的内容写入string字符串中</span></span><br><span class="line">	string buf;</span><br><span class="line">	<span class="keyword">while</span> (<span class="built_in">getline</span>(ifs, buf)) <span class="comment">//全局函数getline()，参数一：流，这里是文件读取流，参数二：字符串</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; buf &lt;&lt; endl;</span><br><span class="line">	&#125;</span><br><span class="line">	ifs.<span class="built_in">close</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">read4</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	ifstream ifs;<span class="comment">//创建流对象</span></span><br><span class="line">	ifs.<span class="built_in">open</span>(<span class="string">&quot;test.txt&quot;</span>, ios::in);<span class="comment">//打开文件并</span></span><br><span class="line">	<span class="keyword">if</span> (!ifs.<span class="built_in">is_open</span>())<span class="comment">//判断文件是否打开成功</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;文件打开失败&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">//读数据</span></span><br><span class="line">		<span class="comment">//第四种，将文件中的内容一个一个的读取并写入到一个char字符中，一个一个的输出，效率低</span></span><br><span class="line">	<span class="type">char</span> c;</span><br><span class="line">	<span class="keyword">while</span> ((c = ifs.<span class="built_in">get</span>()) != EOF)	<span class="comment">//EOF	end of file	</span></span><br><span class="line">        							<span class="comment">//使用ifs下的get()函数，获取单个字符，并赋值给字符c，然后输出，并判断是否读取到文章尾部，到尾部则停止</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; c;</span><br><span class="line">	&#125;</span><br><span class="line">	ifs.<span class="built_in">close</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="二进制文件"><a href="#二进制文件" class="headerlink" title="二进制文件"></a>二进制文件</h2><hr>
<h3 id="写文件-1"><a href="#写文件-1" class="headerlink" title="写文件"></a>写文件</h3><hr>
<p>以二进制的方式对文件进行读写，操作打开方式要指定为<code>ios:binary</code>。</p>
<p>二进制方式写文件主要利用流对象调用成员函数<code>write</code>。</p>
<p>对于一些复杂数据类型如：<code>string</code>，可以正确写入，但无法正确读取，需要避免使用。</p>
<p>整体步骤与上述文本文件读写步骤一样。</p>
<ul>
<li>函数原型:<code>ostream&amp; write( const char * buffer ,int len)</code></li>
<li>参数解释:字符指针<code>buffer</code>指向内存中一段存储空间。<code>len</code>是读写的字节数</li>
</ul>
<p>示例（以二进制形式写入自定义数据类型）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;fstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> age = <span class="number">0</span>;</span><br><span class="line">	<span class="type">char</span> name[<span class="number">64</span>] = <span class="string">&quot;&quot;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">write_2</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">ofstream <span class="title">ofs</span><span class="params">(<span class="string">&quot;test2.txt&quot;</span>, ios::out | ios::binary)</span></span>;</span><br><span class="line">	person 张三&#123; <span class="number">20</span>, <span class="string">&quot;张三&quot;</span> &#125;;</span><br><span class="line">	ofs.<span class="built_in">write</span>((<span class="type">const</span> <span class="type">char</span>*)&amp;张三, <span class="built_in">sizeof</span>(张三));</span><br><span class="line">	ofs.<span class="built_in">close</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">write_2</span>();</span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<h3 id="读文件-1"><a href="#读文件-1" class="headerlink" title="读文件"></a>读文件</h3><hr>
<p>以二进制的方式对文件进行读写，操作打开方式要指定为<code>ios:binary</code>。</p>
<p>二进制方式读文件主要利用流对象调用成员函数<code>read</code>。</p>
<p>对于一些复杂数据类型如：<code>string</code>，无法正确读取，需要避免使用。</p>
<p>整体步骤与上述文本文件读写步骤一样。</p>
<ul>
<li>函数原型:<code>istream&amp; read(char *buffer,int len) </code></li>
<li>参数解释:字符指针<code>buffer</code>指向内存中一段存储空间。<code>len</code>是读写的字节数</li>
</ul>
<p>示例（将上一个示例中的自定义数据类型读回来）：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">read_2</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="function">ifstream <span class="title">ifs</span><span class="params">(<span class="string">&quot;test2.txt&quot;</span>, ios::in | ios::binary)</span></span>;</span><br><span class="line">	<span class="keyword">if</span> (!ifs.<span class="built_in">is_open</span>())<span class="comment">//判断文件是否打开成功</span></span><br><span class="line">	&#123;</span><br><span class="line">		cout &lt;&lt; <span class="string">&quot;文件打开失败&quot;</span> &lt;&lt; endl;</span><br><span class="line">		<span class="keyword">return</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	person p2;</span><br><span class="line">	ifs.<span class="built_in">read</span>((<span class="type">char</span>*)&amp;p2, <span class="built_in">sizeof</span>(p2));</span><br><span class="line">	ifs.<span class="built_in">close</span>();</span><br><span class="line">	cout &lt;&lt; p2.name &lt;&lt; <span class="string">&quot;  &quot;</span> &lt;&lt; p2.age &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<h2 id="补充说明"><a href="#补充说明" class="headerlink" title="补充说明"></a>补充说明</h2><hr>
<p>C++新标准（C++11及更高版本）引入了一些新特性和库，其中一些与文件操作相关。</p>
<p>下面是一些在C++新标准中与文件操作相关的内容：</p>
<ol>
<li><p><code>std::filesystem</code>：C++17引入了 <code>&lt;filesystem&gt;</code> 头文件，提供了对文件系统的访问和操作。它包含了一组类和函数，使您能够进行文件和目录的创建、复制、移动、重命名等操作，以及获取文件的属性和路径等信息。</p>
</li>
<li><p><code>std::ifstream::open()</code> 重载：</p>
<p>C++11引入了一个新的 <code>std::ifstream</code> 成员函数的重载形式，使您能够更方便地打开文件并指定打开模式。</p>
<p>例如，您可以使用 <code>std::ifstream::open(const std::string&amp; filename, std::ios_base::openmode mode)</code> 重载函数来打开文件并指定读取模式、写入模式、二进制模式等。</p>
</li>
<li><p><code>std::ofstream::open()</code> 重载：</p>
<p>类似地，C++11还引入了 <code>std::ofstream</code> 的 <code>open()</code> 函数重载形式，使您能够更灵活地打开文件并指定打开模式。</p>
</li>
<li><p>移动语义和右值引用：C++11引入了移动语义和右值引用的概念，使您能够更高效地处理文件流对象。通过使用 <code>std::move()</code> 函数，您可以将文件流对象的所有权从一个对象转移到另一个对象，而无需执行深拷贝。</p>
</li>
<li><p>等等……</p>
</li>
</ol>
<p>这些是C++新标准中与文件操作相关的主要内容。它们提供了更强大和灵活的文件操作功能，使您能够更方便地处理文件和文件系统。</p>
<p>请注意，具体实现可能会因编译器和标准库的版本而有所不同，因此请查阅相关的参考文档以了解详细的用法和支持情况。</p>
<h1 id="预处理器"><a href="#预处理器" class="headerlink" title="预处理器"></a>预处理器</h1><h2 id="define"><a href="#define" class="headerlink" title="#define"></a><code>#define</code></h2><h3 id="简单的文本替换"><a href="#简单的文本替换" class="headerlink" title="简单的文本替换"></a>简单的文本替换</h3><p>语法描述：</p>
<p><code>#define name stuff</code></p>
<p>有了这条指令以后，每当<code>name</code>出现在这条指令后面时，预处理器就会把它替换成<code>stuff</code>。</p>
<p>替换文本并不限于数值字面值常量。使用<code>#define</code>指令，可以把任何文本替换到程序中。</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#define reg 			register</span><br><span class="line">#define do_fprever 		for(;;)</span><br><span class="line">#define CASE			break;case;</span><br></pre></td></tr></table></figure></div>

<p>第1个定义只是为关键字<code>register</code>创建了一个简短的别名。</p>
<p>这个较短的名字使各个声明更容易通过制表符进行排列。</p>
<p>第2条声明用一个更具描述性的符号来代替一种用于实现无限循环的for语句类型。</p>
<p>最后一个<code>#define</code>定义了一种简短记法，以便在<code>switch</code>语句中使用。它自动地把一个<code>break</code>放在每个<code>case</code>之前，这使得<code>switch</code>语句看上去更像其他语言的<code>case</code>语句。</p>
<p>如果定义中的stuff非常长，它可以分成几行，除了最后一行之外，每行的末尾都要加一个反斜杠，如下面的例子所示：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> DEBUG_PRINT		printf( <span class="string">&quot;File %s line %d: &quot;</span> \</span></span><br><span class="line"><span class="meta">								<span class="string">&quot;x=%d, y=%d, z=%d&quot;</span>, \</span></span><br><span class="line"><span class="meta">								__FTLE__, __LINE_,  \</span></span><br><span class="line"><span class="meta">								x, y，z )</span></span><br></pre></td></tr></table></figure></div>

<p>这里利用了相邻的字符串常量被自动连接为一个字符串这个特性。当你调试一个存在许多涉及一组变量的不同计算过程的程序时，这种类型的声明非常有用。</p>
<p>你可以很容易地插入一条调试语句打印出它们的当前值。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">x *= <span class="number">2</span>;</span><br><span class="line">y += x;</span><br><span class="line">z = x * y;</span><br><span class="line">DEBUG_PRINT;</span><br></pre></td></tr></table></figure></div>

<p>&#x3D;&#x3D;注意！：&#x3D;&#x3D;</p>
<p>这条语句在DEBUG_PRINT后面加了一个分号，所以你不应该在宏定义的尾部加上分号。</p>
<p>如果你这样做了，结果就会产生两条语句：一条<code>printf</code>语句后面再加一条空语句。</p>
<p>有些场合只允许出现一条语句，如果放入两条语句就会出现问题，例如：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(<span class="comment">//...</span></span><br><span class="line">)&#123;<span class="comment">//...</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line">DEBUG_PRINT;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;<span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>所以，不要滥用这种技巧。如果相同的代码需要出现在程序的几个地方，通常更好的方法是把它实现为一个函数。后续将详细讨论<code>#define</code>宏和函数之间的优劣。</p>
<h3 id="宏函数"><a href="#宏函数" class="headerlink" title="宏函数"></a>宏函数</h3><p><code>#define</code>机制包括了一个规定，允许把参数替换到文本中，这种实现通常称为宏或宏函数。</p>
<p>下面是宏函数的声明方式：</p>
<p><code>#define　name(parameter-list)　 stuff</code></p>
<p>其中，<code>parameter-list</code>（参数列表）是一个由逗号分隔的符号列表，它们可能出现在<code>stuff</code>中。</p>
<p>参数列表的左括号必须与<code>name</code>紧邻。如果两者之间有任何空白存在，参数列表就会被解释为<code>stuff</code>的一部分。</p>
<p><em>&#x3D;&#x3D;以下内容宏函数全部简称为宏。&#x3D;&#x3D;</em></p>
<p>当宏被调用时，名字后面是一个由逗号分隔的值的列表，每个值都与宏定义中的一个参数相对应，整个列表用一对括号包围。</p>
<p>当参数出现在程序中时，与每个参数对应的实际值都将被替换到<code>stuff</code>中。</p>
<hr>
<p>这里有一个宏，它接受一个参数：<code>#define SQUARE(x)　　x * x</code></p>
<p>如果在上述声明之后，你把<code>SQUARE( 5 )</code>置于程序中，预处理器就会用下面这个表达式替换上面的表达式：<code>5 * 5</code></p>
<p>&#x3D;&#x3D;注意！：&#x3D;&#x3D;</p>
<p>这个宏存在一个问题。</p>
<p>观察下面的代码段：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">5</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, <span class="built_in">SQUARE</span>( a + <span class="number">1</span> ));</span><br></pre></td></tr></table></figure></div>

<p>你可能觉得这段代码将打印36这个值。事实上，它将打印11。</p>
<p>参数<code>x</code>被文本<code>a + 1</code>替换，所以这条语句实际上变成了：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">printf(&quot;%d\n&quot;, a + 1 * a + 1);</span><br></pre></td></tr></table></figure></div>

<p>可知：由替换产生的表达式并没有按照预想的次序进行求值。</p>
<p>在宏定义中加上两个括号，这个问题便很轻松地解决了：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> SQUARE(x)　　(x) * (x)</span></span><br></pre></td></tr></table></figure></div>

<p>在前面那个例子里，预处理器现在将用下面这条语句执行替换，从而产生预期的结果：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">printf(&quot;%d\n&quot;, (a + 1) * (a + 1));</span><br></pre></td></tr></table></figure></div>

<hr>
<p>这里有另外一个宏定义：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span>　DOUBLE(x)　　(x) + (x)</span></span><br></pre></td></tr></table></figure></div>

<p>定义中使用了括号，用于避免前面出现的问题。</p>
<p>但是，使用这个宏，可能会出现另外一个不同的错误。下面这段代码将打印出什么值？</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="number">5</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, <span class="number">10</span> * <span class="built_in">DOUBLE</span>( a ) );</span><br></pre></td></tr></table></figure></div>

<p>看上去，它好像将打印100，但事实上它打印的是55。</p>
<p>再一次，通过观察宏替换产生的文本，我们能够发现问题所在：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, <span class="number">10</span> * (a) + (a));</span><br></pre></td></tr></table></figure></div>

<p>乘法运算在宏所定义的加法运算之前执行。</p>
<p>这个错误很容易修正：在定义宏时，你只要在整个表达式两边加上一对括号就可以了：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span>　DOUBLE(x)　　((x) + (x))</span></span><br></pre></td></tr></table></figure></div>

<p>所有用于对数值表达式进行求值的宏定义都应该用这种方式加上括号，避免在使用宏时，由于参数中的操作符或邻近的操作符之间不可预料的相互作用。</p>
<p>下面是一对有趣的宏：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span>　repeat　　do</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span>　until(x)　　while(!(x))</span></span><br></pre></td></tr></table></figure></div>

<p>这两个宏创建了一种“新”的循环，其工作过程类似于其他语言中的<br><code>repeat/until</code>循环。它按照下面这样的方式使用：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">repeat &#123;</span><br><span class="line">	statements</span><br><span class="line">&#125;<span class="built_in">until</span>( i &gt;= <span class="number">10</span>);</span><br></pre></td></tr></table></figure></div>

<p>预处理器将用下面的代码进行替换：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">	statements</span><br><span class="line">&#125; <span class="keyword">while</span>( !(i &gt;= <span class="number">10</span>));</span><br></pre></td></tr></table></figure></div>

<p>表达式<code>i&gt;=10</code>两边的括号用于确保在<code>!</code>操作符执行之前先完成这个表达式的求值。</p>
<p>&#x3D;&#x3D;注意！：&#x3D;&#x3D;</p>
<p>创建一套<code>#define</code>宏，用一种看上去很像其他语言的方式编写C程序是完全可能的。</p>
<p>在绝大多数情况下，你应该避免这种诱惑，因为这样编写出来的程序使其他C程序员很难理解。</p>
<p>他们必须时常查阅这些宏的定义以便弄清实际的代码是什么意思。</p>
<p>即使每个和这个项目生命期各个阶段相关的人都熟悉那种被模仿的语言，这个技巧仍然可能引起混淆，因为准确地模仿其他语言的各个方面是极为困难的。</p>
<hr>
<p>当预处理器搜索<code>#define</code>定义的符号时，字符串常量的内容并不进行检查。你如果想把宏参数插入到字符串常量中，可以使用两种技巧：</p>
<ul>
<li>第1个技巧邻近字符串自动连接的特性使我们很容易把一个字符串分成几段，每段实际上都是一个宏参数。这里有一个这种技巧的例子：</li>
</ul>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> PRINT(FORMAT ,VALUE)		\</span></span><br><span class="line"><span class="meta">		printf ( <span class="string">&quot;The value is &quot;</span> FORMAT <span class="string">&quot;n&quot;</span> , VALUE)</span></span><br><span class="line">		<span class="built_in">PRINT</span>(<span class="string">&quot;%d&quot;</span> ,x +<span class="number">3</span> ) ;</span><br></pre></td></tr></table></figure></div>

<p>这种技巧只有当字符串常量作为宏参数给出时才能使用。</p>
<ul>
<li><p>第2个技巧使用预处理器把一个宏参数转换为一个字符串。#argument这种结构<br>被预处理器翻译为“argument”。这种翻译可以让你像下面这样编写代码：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> PRINT (FORMAT，VALUE)					\</span></span><br><span class="line"><span class="meta">		printf ( <span class="string">&quot;The value of &quot;</span>#VALUE			\</span></span><br><span class="line"><span class="meta">		<span class="string">&quot;is &quot;</span> FORMAT <span class="string">&quot; \n&quot;</span>, VALUE )	</span></span><br><span class="line">		<span class="built_in">PRINT</span>(<span class="string">&quot;%d&quot;</span>,x + <span class="number">3</span> );</span><br></pre></td></tr></table></figure></div>

<p>它将产生下面的输出：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">The value of x +3 is 25</span><br></pre></td></tr></table></figure></div></li>
</ul>
<hr>
<p><code>##</code>结构则执行一种不同的任务：它把位于它两边的符号连接成一个符号。</p>
<p>作为用途之一，它允许宏定义从分离的文本片段创建标识符。</p>
<p>下面这个例子使用这种连接把一个值添加到几个变量之一：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> ADD_To_SUM(sum_number, value ) \</span></span><br><span class="line"><span class="meta">		sum##sum_number += value</span></span><br><span class="line">		<span class="built_in">ADD_TO_SUM</span>(<span class="number">5</span>,<span class="number">25</span>) ;</span><br></pre></td></tr></table></figure></div>

<p>最后一条语句把值25加到变量sum5。</p>
<p>注意这种连接必须产生一个合法的标识符。否则，其结果就是未定义的。</p>
<h3 id="宏的优势缺陷"><a href="#宏的优势缺陷" class="headerlink" title="宏的优势缺陷"></a>宏的优势缺陷</h3><p>在程序中扩展<code>#define</code>定义符号和宏时，需要涉及几个步骤。</p>
<ul>
<li>在调用宏时，首先对参数进行检查，看看是否包含了任何由<code>#define</code>定义的符号。如果是，它们首先被替换。</li>
<li>替换文本随后被插入到程序中原来文本的位置。对于宏，参数名被它们的值所替代。</li>
<li>最后，再次对结果文本进行扫描，看看它是否包含了任何由<code>#define</code>定义的符号。如果是，就重复上述处理过程。</li>
</ul>
<p>这样，宏参数和<code>#define</code>定义可以包含其他<code>#define</code>定义的符号。但是，宏不可以出现递归。</p>
<hr>
<p>宏非常频繁地用于执行简单的计算，比如在两个表达式中寻找其中较大（或较小）的一个：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAX( a, b )　　( (a) &gt; (b) ? (a) : (b) )</span></span><br></pre></td></tr></table></figure></div>

<p>为什么不用函数来完成这个任务呢？</p>
<p>有两个原因：</p>
<ul>
<li><p>首先，用于调用和从函数返回的代码很可能比实际执行这个小型计算工作的代码更大，所以使用宏比使用函数在程序的规模和速度方面都更胜一筹。</p>
<p>但是，更为重要的是，函数的参数必须声明为一种特定的类型，所以它只能在类型合适的表达式上使用。</p>
</li>
<li><p>反之，上面这个宏可以用于整型、长整型、单浮点型、双浮点数以及其他任何可以用&gt;操作符比较值大小的类型。</p>
<p>换句话说，宏是与类型无关的。和使用函数相比，使用宏的不利之处在于每次使用宏时，一份宏定义代码的拷贝都将插入到程序中。</p>
<p>除非宏非常短，否则使用宏可能会大幅度增加程序的长度。</p>
</li>
</ul>
<p>&#x3D;&#x3D;还有一些任务根本无法用函数实现。&#x3D;&#x3D;</p>
<p>这个宏的第2个参数是一种类型，它无法作为函数参数进行传递。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MALLOC(n, type) \</span></span><br><span class="line"><span class="meta">　　　　 ( (type *)malloc( (n) * sizeof( type ) ) )</span></span><br></pre></td></tr></table></figure></div>

<p>下面这个例子中的第1条语句被预处理器转换为第2条语句。</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pi = MALLOC( 25, int );</span><br><span class="line">pi = ( ( int * )malloc( ( 25 ) * sizeof( int ) ) );</span><br></pre></td></tr></table></figure></div>

<p>同样，请注意宏定义并没有用一个分号结尾。分号出现在调用这个宏的语句中。</p>
<hr>
<p>当宏参数在宏定义中出现的次数超过一次时，如果这个参数具有副作用，那么当你使用这个宏时就可能出现危险，导致不可预料的结果。</p>
<p>副作用就是在表达式求值时出现的永久性效果。例如，这个表达式<code>x + 1</code>可以重复执行几百次，它每次获得的结果都是一样的。这个表达式不具有副作<br>用。</p>
<p>但是<code>x++</code>就具有副作用：它增加<code>x</code>的值。当这个表达式下一次执行时，它将产生一个不同的结果。</p>
<p><code>MAX</code>宏可以证明具有副作用的参数所引起的问题：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAX(a, b) ((a) &gt; (b) ? (a) : (b))</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    x = <span class="number">5</span> ;y = <span class="number">8</span> ;</span><br><span class="line">	z = <span class="built_in">MAX</span>(x++,y++ ) ;</span><br><span class="line">	<span class="built_in">printf</span> ( <span class="string">&quot;x=%d, y=%d，z=%d\n&quot;</span> , x, y, z );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>其结果是：<code>x=6，y=10，z=9</code></p>
<p>关于为什么，只要检查一下用宏替换后产生的代码，这个奇怪的结果就变得一目了然了：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">z = ((x++) &gt; (y++) ? (x++) : (y++));</span><br></pre></td></tr></table></figure></div>

<p>虽然那个较小的值只增值了一次，但那个较大的值却增值了两次：第1次是在比较时，第2次在执行?符号后面的表达式时出现。</p>
<hr>
<p>下面这个宏：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> EVENPARITY(ch)					\</span></span><br><span class="line"><span class="meta">		(( count__one_bits (ch) &amp; 1 ) ?	\</span></span><br><span class="line"><span class="meta">		(ch) | PARITYBIT : (ch))</span></span><br></pre></td></tr></table></figure></div>

<p>该函数返回它的参数的二进制位模式中1的个数。这个宏的目的是产生一个具有偶校验的字符。</p>
<p>它首先计数字符中位1的个数，如果结果是一个奇数，PARITYBIT值（一个值为1的位）与该字符执行OR操作，否则该字符就保留不变。</p>
<p>但是，当这个宏以下面这种方式使用时：</p>
<p><code>ch = EVENPARITY( getchar() );</code></p>
<p>读取一个字符并计算它的校验位。但是，它的结果是失败的，因为它实际上读入了两个字符！</p>
<hr>
<p>宏和函数的不同之处：</p>
<table>
<thead>
<tr>
<th align="left"></th>
<th><code>#define</code>宏</th>
<th>函数</th>
</tr>
</thead>
<tbody><tr>
<td align="left">代码长度</td>
<td>每次使用时，宏代码都被插入到程序中。除了非常小的宏之外，程序的长度将大幅度增长</td>
<td>函数代码只出现于一个地方；每次使用这个函数时，都调用那个地方的同一份代码</td>
</tr>
<tr>
<td align="left">执行速度</td>
<td>更快</td>
<td>存在函数调用&#x2F;返回的额外开销</td>
</tr>
<tr>
<td align="left">操作符优先级</td>
<td>宏参数的求值是在所有周围表达式的上下文环境里，除非它们加上括号，否则邻近操作符的优先级可能会产生不可预料的结果</td>
<td>函数参数只在函数调用时求值一次，它的结果值传递给函数。表达式的求值结果更容易预测</td>
</tr>
<tr>
<td align="left">参数求值</td>
<td>参数每次用于宏定义时，它们都将重新求值。由于多次求值，具有副作用的参数可能会产生不可预料的结果</td>
<td>参数在函数被调用前只求值一次。在函数中多次使用参数并不会导致多种求值过程。参数的副作用并不会造成任何特殊的问题</td>
</tr>
<tr>
<td align="left">参数类型</td>
<td>宏与类型无关。只要对参数的操作是合法的，它可以使用于任何参数类型</td>
<td>函数的参数是与类型有关的。如果参数的类型不同，就需要使用不同的函数，即使它们执行的任务是相同的</td>
</tr>
</tbody></table>
<h3 id="命名约定"><a href="#命名约定" class="headerlink" title="命名约定"></a>命名约定</h3><p><code>#define</code>宏的行为和真正的函数相比存在一些不同的地方，上表对此进行了总结。</p>
<p>由于这些不同之处，所以让程序员知道一个标识符究竟是一个宏还是一个函数是非常重要的。</p>
<p>但是使用宏的语法和使用函数的语法是完全一样的，所以语言本身并不能帮助你区分这两者。</p>
<p>为宏定义（对于绝大多数由<code>#define</code>定义的符号也是如此）采纳一种命名约定是很重要的，上面这种混淆就是促使人们这样做的原因之一。</p>
<p>一个常见的约定就是把宏名字全部大写。</p>
<p>在下面这条语句中：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value = <span class="built_in">max</span>( a, b );</span><br></pre></td></tr></table></figure></div>

<p><code>max</code>究竟是一个宏还是一个函数并不明显。</p>
<p>你很可能不得不仔细察看源文件以及它所包含的所有头文件来找出它的真实身份。</p>
<p>另一方面，请看下面这条语句：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">value = <span class="built_in">MAX</span>( a, b );</span><br></pre></td></tr></table></figure></div>

<p>命名约定使<code>MAX</code>的身份一清二楚。</p>
<p>如果宏使用可能具有副作用的参数时，这个约定尤为重要，因为它可以提醒程序员在使用宏之前先把参数存储到临时变量中。</p>
<h2 id="undef"><a href="#undef" class="headerlink" title="#undef"></a><code>#undef</code></h2><p>语法描述：</p>
<p><code>#undef　name</code></p>
<p>用于移除一个已有的宏定义<code>name</code>，让后续代码中无法再使用该宏。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个宏，用于计算两个数的平方</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SQUARE(x) ((x) * (x))</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> number = <span class="number">5</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 使用宏计算5的平方</span></span><br><span class="line">    <span class="type">int</span> result = <span class="built_in">SQUARE</span>(number);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;5的平方是: %d\n&quot;</span>, result);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 取消宏定义</span></span><br><span class="line">    <span class="meta">#<span class="keyword">undef</span> SQUARE</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 尝试再次使用宏，现在会报错</span></span><br><span class="line">    result = <span class="built_in">SQUARE</span>(number); <span class="comment">// Uncommenting this line will cause a compilation error</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>代码中使用<code>#undef SQUARE</code>取消了宏定义，后续代码中将无法再使用<code>SQUARE</code>宏，再次尝试使用宏时会导致编译错误。</p>
<p>如果一个现存的名字需要被重新定义，那么它的旧定义首先必须用<code>#undef</code>移除。</p>
<p>示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义一个宏，表示一个最大值MAXNUM为100</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> MAXNUM 100</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;MAXNUM的值是: %d\n&quot;</span>, MAXNUM); <span class="comment">//打印100</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 取消宏定义</span></span><br><span class="line">    <span class="meta">#<span class="keyword">undef</span> MAXNUM</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重新定义宏，MAXNUM为1000</span></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> MAXNUM 1000</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 再次打印</span></span><br><span class="line">     <span class="built_in">printf</span>(<span class="string">&quot;MAXNUM的值是: %d\n&quot;</span>, MAXNUM); <span class="comment">//打印1000</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div>

<h2 id="条件编译"><a href="#条件编译" class="headerlink" title="条件编译"></a>条件编译</h2><h3 id="选择性编译"><a href="#选择性编译" class="headerlink" title="选择性编译"></a>选择性编译</h3><p>在编译一个程序时，如果我们可以选择只对某些语句进行编译或者忽略，常常会显得很方便。</p>
<p>这些语句不应该出现在程序的产品版本中，但是你可能并不想把这些语句从源代码中物理删除，因为如果需要一些维护性修改时，你可能需要重新调试这个程序，还需要这些语句。</p>
<p>条件编译就是用于实现这个目的。使用条件编译，你可以选择代码的一部分是被正常编译还是完全忽略。</p>
<p>用于条件编译的指令包括：<code>#if</code>、<code>#endif</code>、<code>#ifdef</code>、<code>#ifndef</code>、<code>#else</code>、<code>#elif</code>。</p>
<p>下面显示了它最简单的语法形式：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">if</span>　constant-expression</span></span><br><span class="line">　　　　 statements</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure></div>

<p>其中，<code>constant-expression</code>是一个常量表达式，由预处理器进行求值。</p>
<p>如果它的值是非零值即真值，那么<code>statements</code>部分就被正常编译，否则预处理器就“安静地删除“它们，使得<code>statements</code>部分在编译时被忽略。</p>
<p>所谓常量表达式，就是说它或者是字面值常量，或者是一个由<code>#define</code>定义的符号。</p>
<p>如果变量在执行期之前无法获得它们的值，那么它们如果出现在常量表达式中就是非法的，不同的编译器可能有不同的处理方式：忽略、报错等，因为它们的值在编译时是不可预测的。</p>
<p>例如：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">if</span> DEBUG</span></span><br><span class="line"><span class="built_in">printf</span> ( <span class="string">&quot;x=%d, y=%dn&quot;</span> , x, y ) ;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure></div>

<p><code>DEBUG</code>的值并没有指定，这实际上是一种未定义行为，不同的编译器可能有不同的处理方式：有的编译器会将未定义的宏视为零（假），有的编译器会发出警告，有的编译器可能会忽略这段代码或者报错。</p>
<p>为了避免这种未定义行为，正确的做法是在代码中明确地定义 <code>DEBUG</code> 宏，如果想要编译它，只要使用：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> DEBUG 1  </span></span><br></pre></td></tr></table></figure></div>

<p>如果想要忽略它，只要把这个符号定义为0就可以了。无论哪种情况，这段代码都可以保留在源文件中。</p>
<p>这样，预处理指令 <code>#if DEBUG</code> 就能正确地根据 <code>DEBUG</code> 宏的定义与否来决定是否编译相关代码。</p>
<p>当使用条件预处理指令 <code>#if</code> 时，可以结合 <code>#elif</code> 和 <code>#else</code> 子句来实现多个条件的判断。</p>
<p>完整的语法如下所示：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> OPTION 2</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> OPTION == 1</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Option 1 is selected.\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">elif</span> OPTION == 2</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Option 2 is selected.\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">elif</span> OPTION == 3</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Option 3 is selected.\n&quot;</span>);</span><br><span class="line">    </span><br><span class="line"><span class="comment">//......</span></span><br><span class="line">    </span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;Option is not recognized.\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这个示例中，我们定义了一个宏 <code>OPTION</code>，然后使用条件预处理指令 <code>#if</code> 和 <code>#elif</code> 来判断不同的选项。</p>
<p>根据 <code>OPTION</code> 的值，程序将输出不同的信息。</p>
<ul>
<li>如果 <code>OPTION</code> 的值为 <code>1</code>，那么编译器会选择第一个条件分支 <code>#if OPTION == 1</code>，输出 “Option 1 is selected.”</li>
<li>如果 <code>OPTION</code> 的值为 <code>2</code>，那么编译器会选择第二个条件分支 <code>#elif OPTION == 2</code>，输出 “Option 2 is selected.”</li>
<li>如果 <code>OPTION</code> 的值既不是 <code>1</code> 也不是 <code>2</code>，编译器会选择最后的 <code>#else</code> 分支，输出 “Option is not recognized.”</li>
</ul>
<p>在实际的项目中，通过调整宏的定义，可以灵活地根据不同的条件编译不同的代码，这在实现跨平台、调试开关等方面非常有用。</p>
<h3 id="检查是否定义"><a href="#检查是否定义" class="headerlink" title="检查是否定义"></a>检查是否定义</h3><p>当使用条件编译时，我们可以通过<code>#ifdef</code>和<code>#ifndef</code>来检查符号是否已经被定义。</p>
<p>下面是一个简单的例子：</p>
<p>假设我们有一个程序，其中使用了一个预定义的符号<code>DEBUG</code>来控制是否打印调试信息。</p>
<p>如果<code>DEBUG</code>已经被定义，则打印调试信息；如果没有定义，则不打印调试信息。</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> DEBUG <span class="comment">// 如果定义了DEBUG符号时，打印调试信息</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> DEBUG_PRINT(x) std::cout&lt;&lt;x;</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">else</span> <span class="comment">//没有定义就空实现一段代码</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> DEBUG_PRINT(x) do &#123;&#125; while (0)</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> num = <span class="number">42</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 输出调试信息</span></span><br><span class="line">    DEBUG_PRINT((<span class="string">&quot;Debug: The value of num is %d\n&quot;</span>, num));</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 其他代码...</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这个例子中，我们使用了<code>#ifdef DEBUG</code>和<code>#ifndef DEBUG</code>来检查<code>DEBUG</code>符号是否已经被定义。</p>
<ul>
<li><p><code>#ifdef DEBUG</code> 表示：检查是否已经定义了<code>DEBUG</code>符号。</p>
<p>如果已经定义，就会编译<code>#ifdef</code>后面的代码块，这里我们定义了一个宏<code>DEBUG_PRINT(x)</code>，它会调用<code>cout</code>来打印调试信息。</p>
</li>
<li><p><code>#ifndef DEBUG</code> 表示：检查是否没有定义<code>DEBUG</code>符号。</p>
<p>如果没有定义，就会编译<code>#ifndef</code>后面的代码块，这里我们定义了一个空的<code>DEBUG_PRINT(x)</code>宏，这样在程序中调用<code>DEBUG_PRINT</code>时就不会有任何输出，达到不打印调试信息的目的。</p>
</li>
</ul>
<p>在编译程序时，可以通过在编译命令中加入<code>-DDEBUG</code>选项来定义<code>DEBUG</code>符号，或者不加该选项则表示没有定义<code>DEBUG</code>符号。</p>
<p>这样，程序在不同的编译情况下会根据<code>DEBUG</code>符号的定义与否，选择性地打印或不打印调试信息。</p>
<h3 id="防止头文件重复包含"><a href="#防止头文件重复包含" class="headerlink" title="防止头文件重复包含"></a>防止头文件重复包含</h3><p>可以使用预处理指令来防止头文件重复包含。</p>
<p>头文件重复包含可能导致编译错误或其他问题，因此需要使用预处理指令来确保头文件只被包含一次。</p>
<p>常用的预处理指令有两种：<code>#ifndef</code>和<code>#pragma once</code>。这里只将使用条件编译的方式。</p>
<p>在每个头文件的开头，我们可以使用<code>#ifndef</code>、<code>#define</code>和<code>#endif</code>组合来防止重复包含。</p>
<p>这样的组合通常被称为“头文件保护”或“宏保护”。</p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> MY_HEADER_H  <span class="comment">// 检查是否没有定义过MY_HEADER_H</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> MY_HEADER_H  <span class="comment">// 如果没有定义，则定义MY_HEADER_H</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 头文件的内容写在这里</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span>  <span class="comment">// 结束宏保护</span></span></span><br></pre></td></tr></table></figure></div>

<p>当编译器第一次遇到该头文件时，<code>MY_HEADER_H</code>还没有被定义，所以<code>#ifndef</code>条件为真，然后执行<code>#define MY_HEADER_H</code>，将<code>MY_HEADER_H</code>定义为一个标识符。</p>
<p>当其他地方再次包含这个头文件时，由于<code>MY_HEADER_H</code>已经被定义了，所以<code>#ifndef</code>条件为假，头文件的内容就会被跳过，从而避免了重复包含。</p>
<h3 id="嵌套指令"><a href="#嵌套指令" class="headerlink" title="嵌套指令"></a>嵌套指令</h3><p>当进行条件编译时，的确可以嵌套使用多个条件，这样可以根据多个条件来选择性地编译代码块。</p>
<p>我们使用一个更简单的示例来说明嵌套条件编译的概念：</p>
<p>假设有一个宏 <code>DEBUG_MODE</code>，用于控制是否打印调试信息。</p>
<p>还有一个宏 <code>TEST_MODE</code>，用于控制是否编译测试相关的代码。</p>
<p>下面是一个简单的示例代码：</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> DEBUG_MODE</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> TEST_MODE</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> </span><br><span class="line">&#123;</span><br><span class="line">    <span class="meta">#<span class="keyword">ifdef</span> DEBUG_MODE</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;已启用调试模式。\n&quot;</span>);</span><br><span class="line">    <span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="meta">#<span class="keyword">ifdef</span> TEST_MODE</span></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;已启用测试模式。\n&quot;</span>);</span><br><span class="line">    <span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="meta">#<span class="keyword">ifdef</span> DEBUG_MODE</span></span><br><span class="line">        <span class="meta">#<span class="keyword">ifdef</span> TEST_MODE</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;已同时启用调试模式和测试模式。\n&quot;</span>);</span><br><span class="line">        <span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;已启用调试模式，但未启用测试模式。\n&quot;</span>);</span><br><span class="line">        <span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">        <span class="meta">#<span class="keyword">ifdef</span> TEST_MODE</span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;已启用测试模式，但未启用调试模式。\n&quot;</span>);</span><br><span class="line">        <span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;未启用调试模式和测试模式。\n&quot;</span>);</span><br><span class="line">        <span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>在这个示例中，我们使用了嵌套的条件编译来处理四种情况：</p>
<ol>
<li>如果只有 <code>DEBUG_MODE</code> 被定义，输出：已启用调试模式。</li>
<li>如果只有 <code>TEST_MODE</code> 被定义，输出：已同时启用调试模式和测试模式。</li>
<li>如果两者都被定义，输出：已启用调试模式，但未启用测试模式。</li>
<li>如果两者都没有被定义，输出：已启用测试模式，但未启用调试模式。</li>
</ol>
<h3 id="其他注意事项"><a href="#其他注意事项" class="headerlink" title="其他注意事项"></a>其他注意事项</h3><ul>
<li><p><code>#if defined A</code>和<code> #ifdef A</code>是等价的。</p>
</li>
<li><p><code>#if !defined A</code>和<code>#ifndef A</code>是等价的。</p>
</li>
<li><p>每一个条件编译都应以<code>#endif</code>结尾。</p>
</li>
</ul>
<h2 id="error"><a href="#error" class="headerlink" title="#error"></a><code>#error</code></h2><p><code>#error</code>指令允许你生成错误信息。编译程序时，只要遇到<code>#error</code> 就会生成一个编译错误提示消息，并停止编译。</p>
<p>语法：<br><code>#error　text of error message</code></p>
<p>代码示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined A</span></span><br><span class="line"></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;define 了 A&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="meta">#<span class="keyword">elif</span> defined B</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;define 了 B&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="meta">#<span class="keyword">elif</span> defined C</span></span><br><span class="line">	cout &lt;&lt; <span class="string">&quot;define 了 C &quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">	<span class="meta">#<span class="keyword">error</span> No defined A B C</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>这段代码编译无法通过。</p>
<p>在程序运行时，一旦遇到断言不成立，程序即会报错终止，以方便程序调试。<code>#error</code>与<code>#if</code>搭配使用可以认为是一个用于调试宏的编译期断言。</p>
<h2 id="include"><a href="#include" class="headerlink" title="#include"></a><code>#include</code></h2><p>我们使用<code>#include</code>指令来包含头文件，以便在代码中引用其中的函数声明、宏或其他定义。</p>
<p>C&#x2F;C++语言标准允许编译器自行决定如何处理两种形式的<code>#include</code>：一种是本地形式，另一种是函数库形式。</p>
<ol>
<li><p>本地形式的<code>#include</code>：</p>
<p>这是指我们在代码中使用相对或绝对路径来引用自己或项目中的头文件。</p>
<p>例如：<code>#include &quot;my_header.h&quot;</code>，其中<code>my_header.h</code>就是本地头文件。</p>
</li>
<li><p>函数库形式的<code>#include</code>：</p>
<p>这是指我们引用标准库或第三方库提供的头文件。</p>
<p>例如：<code>#include &lt;stdio.h&gt;</code>，其中<code>stdio.h</code>就是函数库头文件。</p>
</li>
</ol>
<p>编译器在处理这两种<code>#include</code>时有一个策略：</p>
<ul>
<li>首先，编译器会对本地头文件采用一种特殊的处理方式。它会首先在源文件所在的当前目录中查找要包含的本地头文件。如果能找到，就直接使用这个本地头文件。</li>
<li>如果在当前目录中没有找到本地头文件，编译器则会按照函数库头文件的处理方式来处理它们。这就意味着编译器会在标准位置（通常是系统指定的一些标准目录）去查找本地头文件。</li>
</ul>
<hr>
<p>当我们在代码中使用<code>#include &quot;my_header.h&quot;</code>这样的本地头文件引用时，编译器会按照一种特殊的方式来处理它。</p>
<p>举个例子：</p>
<p>假设我们有一个项目，其中有两个文件，一个是<code>main.c</code>，另一个是<code>my_header.h</code>。</p>
<p><code>main.c</code>文件包含了一些代码，而<code>my_header.h</code>文件定义了一些函数和常量。</p>
<p>现在，我们在<code>main.c</code>中使用了<code>#include &quot;my_header.h&quot;</code>这样的语句来引用<code>my_header.h</code>这个本地头文件。</p>
<ul>
<li><p>如果<code>main.c</code>和<code>my_header.h</code>都在同一个文件夹内，编译器会首先在这个文件夹中查找<code>my_header.h</code>，找到了就直接使用它的内容。</p>
</li>
<li><p>如果<code>my_header.h</code>在另一个文件夹中，比如在<code>include</code>文件夹内，而<code>main.c</code>在项目的根目录中，编译器会先在当前根目录中查找<code>my_header.h</code>，如果找不到，再去<code>include</code>文件夹中找，找到了就使用。</p>
</li>
</ul>
<p>这样的处理方式让我们能够方便地组织项目中的本地头文件，如果在当前目录能找到，就直接使用，找不到再按照标准规则去查找，确保了头文件的引用可以在不同的项目结构中都能正常工作。</p>
<p>这种处理方式的好处是，编译器优先考虑了本地头文件的查找，这样在项目中我们可以方便地使用自定义的头文件。</p>
<p>如果本地头文件不存在，编译器会像处理函数库头文件一样，按照预定的规则去查找它们。</p>
<h2 id="（空指令）"><a href="#（空指令）" class="headerlink" title="#（空指令）"></a><code>#</code>（空指令）</h2><p>无效指令（空指令）就是一个<code>#</code>符号开头，但后面不跟任何内容的一行。这类指令只是被预处理器简单地删除。</p>
<p>下面例子中的无效指令通过把<code>#include</code>与周围的代码分隔开来，凸显它的存在，当然我们也可以通过插入空行取得相同的效果：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#</span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line">#</span><br></pre></td></tr></table></figure></div>

<h2 id="pragma"><a href="#pragma" class="headerlink" title="#pragma"></a><code>#pragma</code></h2><p><code>#pragma</code> 指令通常用于向编译器发出一些特定的指令或控制命令，以便改变编译器的行为或进行一些特定的操作。</p>
<p>&#x3D;&#x3D;它并不是C&#x2F;C++语言标准的一部分，而是由各个编译器厂商提供的扩展功能。&#x3D;&#x3D;</p>
<p>因此，&#x3D;&#x3D;不同的编译器可能支持不同的 <code>#pragma</code> 指令，并且在不同的编译器中可能会有不同的效果。&#x3D;&#x3D;</p>
<p>下面是一些常见的 <code>#pragma</code> 预处理指令和它们的用途：</p>
<ul>
<li><p><code>#pragma once</code>: 这是一个用于防止头文件重复包含的指令，和使用 <code>#ifndef</code> 和 <code>#define</code> 进行头文件保护的效果是一样的。</p>
</li>
<li><p><code>#pragma pack</code>: 这个指令用于设置结构体的字节对齐方式。</p>
<p>可以通过 <code>#pragma pack(n)</code> 将结构体的对齐方式设置为 <code>n</code> 字节。在不同的编译器中，可能会有其他指令用于控制结构体的对齐方式。</p>
</li>
<li><p><code>#pragma message</code>: 这个指令用于在编译过程中输出一条用户定义的消息。例如，用于调试或显示一些编译信息。</p>
<p>例如：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> message(<span class="string">&quot;Compiling my program...&quot;</span>)</span></span><br></pre></td></tr></table></figure></div>
</li>
<li><p><code>#pragma warning</code>: 这个指令用于控制编译器警告的输出。</p>
<p>可以通过 <code>#pragma warning(disable: &lt;warning_code&gt;)</code> 来禁用特定的警告，或者通过 <code>#pragma warning(error: &lt;warning_code&gt;)</code> 将警告转换为错误，中断编译。</p>
<p>例如：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> <span class="keyword">warning</span>(disable: 1234) <span class="comment">// 禁用警告编号为1234的警告</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> <span class="keyword">warning</span>(<span class="keyword">error</span>: 5678)  <span class="comment">// 将警告编号为5678的警告转换为错误</span></span></span><br></pre></td></tr></table></figure></div>

<p>示例：</p>
<p>再MSVC微软旗下的一款编译器中，认为<code>scanf</code>函数是不安全的，编译时会报错，编译无法通过，错误代码为：C4996。</p>
<p>但是可以使用<code>#pragma warning(disable: 4996)</code>来禁用这个错误提示，使得编译顺利通过。</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> <span class="keyword">warning</span>(disable: 4996) <span class="comment">// 禁用警告编号为4996的警告</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="type">int</span> a;</span><br><span class="line">    </span><br><span class="line">	<span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;a);</span><br><span class="line">    </span><br><span class="line">	cout &lt;&lt; a &lt;&lt; endl;</span><br><span class="line">    </span><br><span class="line">	<span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></li>
</ul>
<p>&#x3D;&#x3D;需要注意：#pragma&#96; 不是C&#x2F;C++的标准指令，它的行为和效果可能在不同的编译器中有所不同。&#x3D;&#x3D;</p>
<p>为了保证代码的可移植性，建议尽量避免过度依赖特定的 <code>#pragma</code> 指令。</p>
<p>对于MSVC，详细参阅：<a class="link"   target="_blank" rel="noopener" href="https://learn.microsoft.com/zh-cn/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=msvc-170" >Pragma 指令与 __pragma 和 _Pragma 关键字 | Microsoft Learn <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>
<h2 id="预定义符号"><a href="#预定义符号" class="headerlink" title="预定义符号"></a>预定义符号</h2><h3 id="概述-2"><a href="#概述-2" class="headerlink" title="概述"></a>概述</h3><p>预定义的预处理符号或指令是在编译过程中由编译器自动定义的一些宏或符号。</p>
<p>这些预处理符号可以在代码中使用，用于编写可移植和条件化的代码。</p>
<p>以下是一些常见的预定义的预处理符号或指令：</p>
<ul>
<li><p><code>__LINE__</code>: 这个预处理符号表示当前代码所在的行号，可以在代码中使用，通常用于调试信息输出和错误定位。</p>
</li>
<li><p><code>__FILE__</code>: 这个预处理符号表示当前代码所在的文件名（包括路径），可以在代码中使用，通常用于调试信息输出。</p>
</li>
<li><p><code>__DATE__</code>: 这个预处理符号表示代码被编译的日期，以字符串形式表示（通常是”月 日 年”的格式），可以在代码中使用。</p>
</li>
<li><p><code>__TIME__</code>: 这个预处理符号表示代码被编译的时间，以字符串形式表示（通常是”时:分:秒”的格式），可以在代码中使用。</p>
</li>
<li><p><code>__cplusplus</code>: 这个预处理符号在C++编译器中定义，用于判断当前代码是否是C++环境。如果代码在C++环境中编译，<code>__cplusplus</code> 会被定义为一个非零值，否则未定义。</p>
</li>
<li><p><code>_WIN32</code>、<code>_WIN64</code>: 这些预处理符号通常在Windows平台的编译器中定义，用于判断代码是否在Windows环境中编译。</p>
<p><code>_WIN32</code> 在32位Windows系统上定义，而 <code>_WIN64</code> 在64位Windows系统上定义。</p>
</li>
<li><p><code>__GNUC__</code>: 这个预处理符号在GNU编译器（例如GCC）中定义，用于判断代码是否在GCC环境中编译。</p>
</li>
</ul>
<p>这些预定义的预处理符号或指令可以帮助程序员获取一些关于编译环境和代码位置的信息，并且在编写可移植和条件化代码时非常有用。</p>
<p>需要注意的是，这些预定义符号的名称通常以双下划线开头和结尾，以避免和用户定义的宏冲突。</p>
<h3 id="使用示例"><a href="#使用示例" class="headerlink" title="使用示例"></a>使用示例</h3><ul>
<li><p><code>__LINE__</code> 和 <code>__FILE__</code> 的使用示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;当前代码位于文件 %s 的第 %d 行。\n&quot;</span>, __FILE__, __LINE__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行上述代码，输出可能类似于：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">当前代码位于文件 main.c 的第 5 行。</span><br></pre></td></tr></table></figure></div>
</li>
<li><p><code>__DATE__</code> 和 <code>__TIME__</code> 的使用示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;代码编译日期：%s\n&quot;</span>, __DATE__);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;代码编译时间：%s\n&quot;</span>, __TIME__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行上述代码，输出可能类似于：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">代码编译日期：Jul 28 2023</span><br><span class="line">代码编译时间：18:30:00</span><br></pre></td></tr></table></figure></div>
</li>
<li><p><code>__cplusplus</code> 的使用示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> __cplusplus</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;这是C++环境下的代码。&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;这是C环境下的代码。&quot;</span> &lt;&lt; std::endl;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行上述代码，如果编译器是C++编译器，则输出：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是C++环境下的代码。</span><br></pre></td></tr></table></figure></div>

<p>如果编译器是C编译器，则输出：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是C环境下的代码。</span><br></pre></td></tr></table></figure></div>
</li>
<li><p><code>_WIN32</code> 和 <code>_WIN64</code> 的使用示例：</p>
<div class="highlight-container" data-rel="C++"><figure class="iseeu highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> _WIN32</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;这是在Windows 32位环境下编译的代码。\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">elif</span> defined(_WIN64)</span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;这是在Windows 64位环境下编译的代码。\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">else</span></span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;这不是在Windows环境下编译的代码。\n&quot;</span>);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>运行上述代码，输出根据编译环境的不同可能有所不同。例如，在Windows 64位系统下编译运行：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">这是在Windows 64位环境下编译的代码。</span><br></pre></td></tr></table></figure></div></li>
</ul>
<p>&#x3D;&#x3D;请注意，输出可能因编译环境不同而有所变化。这些预定义的预处理符号在不同的编译器和平台上可能会有不同的定义和行为。&#x3D;&#x3D;</p>
<h2 id="line"><a href="#line" class="headerlink" title="#line"></a><code>#line</code></h2><p><code>#line</code> 指令是预处理器中的一个特殊指令，用于改变源代码中的行号和文件名信息。</p>
<p>它的主要作用是帮助程序员在预处理阶段中调整行号和文件名，从而在编译错误或调试时提供更准确的信息。</p>
<p><code>#line</code> 指令的语法如下：</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">line</span> constant <span class="string">&quot;filename&quot;</span></span></span><br></pre></td></tr></table></figure></div>

<p>其中，<code>constant</code> 是一个整数常量，表示将当前行号修改为指定的值，<code>&quot;filename&quot;</code> 是一个字符串，表示将当前文件名修改为指定的文件名。</p>
<p>通过使用 <code>#line</code> 指令，程序员可以在宏展开或其他情况下，手动调整行号和文件名，以便更好地定位问题和调试代码。</p>
<p><code>#line</code>指令与作用域是无关的。</p>
<p>以下是一个简单的代码示例：</p>
<div class="highlight-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;当前文件：%s，当前行号：%d\n&quot;</span>, __FILE__, __LINE__);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">line</span> 100 <span class="string">&quot;my_code.c&quot;</span></span></span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;当前文件：%s，当前行号：%d\n&quot;</span>, __FILE__, __LINE__);</span><br><span class="line"></span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;当前文件：%s，当前行号：%d\n&quot;</span>, __FILE__, __LINE__);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;当前文件：%s，当前行号：%d\n&quot;</span>, __FILE__, __LINE__);</span><br><span class="line"></span><br><span class="line">	system(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>

<p>输出结果可能类似于：</p>
<div class="highlight-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">当前文件：main.c，当前行号：6</span><br><span class="line">当前文件：my_code.c，当前行号：100</span><br><span class="line">当前文件：my_code.c，当前行号：102</span><br><span class="line">当前文件：my_code.c，当前行号：104</span><br></pre></td></tr></table></figure></div>










        </div>

        

        
            <ul class="post-tags-box">
                
                    <li class="tag-item">
                        <a href="/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">#学习笔记</a>&nbsp;
                    </li>
                
            </ul>
        

        

        
            <div class="article-nav">
                
                    <div class="article-prev">
                        <a class="prev"
                        rel="prev"
                        href="/2023/09/17/CPP11%E8%B5%B7-%E6%96%B0%E7%89%B9%E6%80%A7/"
                        >
                            <span class="left arrow-icon flex justify-center items-center">
                                <i class="fa-solid fa-chevron-left"></i>
                            </span>
                            <span class="title flex justify-center items-center">
                                <span class="post-nav-title-item">C++11起-新特性</span>
                                <span class="post-nav-item">上一篇</span>
                            </span>
                        </a>
                    </div>
                
                
                    <div class="article-next">
                        <a class="next"
                        rel="next"
                        href="/2023/09/17/hello-websites/"
                        >
                            <span class="title flex justify-center items-center">
                                <span class="post-nav-title-item">hello websites</span>
                                <span class="post-nav-item">下一篇</span>
                            </span>
                            <span class="right arrow-icon flex justify-center items-center">
                                <i class="fa-solid fa-chevron-right"></i>
                            </span>
                        </a>
                    </div>
                
            </div>
        


        
    </div>

    
        <div class="toc-content-container">
            <div class="post-toc-wrap">
    <div class="post-toc">
        <div class="toc-title">此页目录</div>
        <div class="page-title">C++基础</div>
        <ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%BC%95%E7%94%A8%EF%BC%88%E5%B7%A6%E5%80%BC%E5%BC%95%E7%94%A8%EF%BC%89"><span class="nav-text">引用（左值引用）</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%92%8C%E8%AF%AD%E6%B3%95"><span class="nav-text">基本概念和语法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9"><span class="nav-text">注意事项</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%95%E7%94%A8%E5%81%9A%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0"><span class="nav-text">引用做函数参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%95%E7%94%A8%E5%81%9A%E5%87%BD%E6%95%B0%E8%BF%94%E5%9B%9E%E5%80%BC"><span class="nav-text">引用做函数返回值</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%95%E7%94%A8%E7%9A%84%E6%9C%AC%E8%B4%A8"><span class="nav-text">引用的本质</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%B8%E9%87%8F%E5%BC%95%E7%94%A8"><span class="nav-text">常量引用</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%87%BD%E6%95%B0-%E9%AB%98%E7%BA%A7%E7%AF%87"><span class="nav-text">函数_高级篇</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BD"><span class="nav-text">函数重载</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="nav-text">基本使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9-1"><span class="nav-text">注意事项</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0"><span class="nav-text">函数的默认参数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84%E5%8D%A0%E4%BD%8D%E5%8F%82%E6%95%B0"><span class="nav-text">函数的占位参数</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%B1%BB%E5%92%8C%E5%AF%B9%E8%B1%A1"><span class="nav-text">类和对象</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E7%9A%84%E5%AE%9A%E4%B9%89%E5%92%8C%E5%B0%81%E8%A3%85"><span class="nav-text">类的定义和封装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#class%E5%92%8Cstruct%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text">class和struct的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0"><span class="nav-text">析构函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8B%B7%E8%B4%9D%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0"><span class="nav-text">拷贝构造函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89%E8%A7%84%E5%88%99"><span class="nav-text">构造函数定义规则</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E6%8B%B7%E8%B4%9D%E4%B8%8E%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="nav-text">深拷贝与浅拷贝</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%88%97%E8%A1%A8"><span class="nav-text">初始化列表</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%9D%99%E6%80%81%E6%88%90%E5%91%98"><span class="nav-text">静态成员</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#this%E6%8C%87%E9%92%88"><span class="nav-text">this指针</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#const%E4%BF%AE%E9%A5%B0%E7%9A%84%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E5%92%8C%E5%AF%B9%E8%B1%A1"><span class="nav-text">const修饰的成员函数和对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BD"><span class="nav-text">成员函数重载</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%99%AE%E9%80%9A%E9%87%8D%E8%BD%BD"><span class="nav-text">普通重载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E9%87%8F%E6%80%A7%E9%87%8D%E8%BD%BD"><span class="nav-text">常量性重载</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%8B%E5%85%83"><span class="nav-text">友元</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%A8%E5%B1%80%E5%87%BD%E6%95%B0%E5%81%9A%E5%8F%8B%E5%85%83"><span class="nav-text">全局函数做友元</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E5%81%9A%E5%8F%8B%E5%85%83"><span class="nav-text">类做友元</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E5%81%9A%E5%8F%8B%E5%85%83"><span class="nav-text">成员函数做友元</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD"><span class="nav-text">运算符重载</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9B%9B%E5%88%99%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD"><span class="nav-text">四则运算符重载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B7%A6%E7%A7%BB%EF%BC%88"><span class="nav-text">左移（&lt;&lt;）运算符重载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%87%AA%E5%A2%9E%EF%BC%88-%EF%BC%89%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD"><span class="nav-text">自增（++）运算符重载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC%EF%BC%88-%EF%BC%89%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD%EF%BC%88%E6%B7%B1%E6%8B%B7%E8%B4%9D%EF%BC%89"><span class="nav-text">赋值（&#x3D;）运算符重载（深拷贝）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%B6%E4%BB%96%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD%E7%9A%84%E8%AF%B4%E6%98%8E"><span class="nav-text">其他运算符重载的说明</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF"><span class="nav-text">继承</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E6%96%B9%E5%BC%8F"><span class="nav-text">继承方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E4%B8%AD%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B"><span class="nav-text">继承中的对象模型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF%E4%B8%AD%E7%9A%84%E6%9E%84%E9%80%A0%E5%92%8C%E6%9E%90%E6%9E%84%E9%A1%BA%E5%BA%8F"><span class="nav-text">继承中的构造和析构顺序</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%90%8C%E5%90%8D%E6%88%90%E5%91%98%E5%A4%84%E7%90%86"><span class="nav-text">同名成员处理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%9A%E7%BB%A7%E6%89%BF"><span class="nav-text">多继承</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%8F%B1%E5%BD%A2%E7%BB%A7%E6%89%BF%E5%92%8C%E8%99%9A%E7%BB%A7%E6%89%BF"><span class="nav-text">菱形继承和虚继承</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%A4%9A%E6%80%81"><span class="nav-text">多态</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%9A%E6%80%81%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="nav-text">多态的概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%99%9A%E5%87%BD%E6%95%B0"><span class="nav-text">虚函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%99%9A%E5%87%BD%E6%95%B0%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90"><span class="nav-text">虚函数原理剖析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BA%AF%E8%99%9A%E5%87%BD%E6%95%B0%E5%92%8C%E6%8A%BD%E8%B1%A1%E7%B1%BB"><span class="nav-text">纯虚函数和抽象类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%99%9A%E6%9E%90%E6%9E%84%E5%92%8C%E7%BA%AF%E8%99%9A%E6%9E%90%E6%9E%84"><span class="nav-text">虚析构和纯虚析构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#override%E5%85%B3%E9%94%AE%E5%AD%97"><span class="nav-text">override关键字</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86"><span class="nav-text">异常处理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95"><span class="nav-text">基本语法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%82%E5%B8%B8%EF%BC%88%E6%8E%A5%E5%8F%A3%EF%BC%89%E5%A3%B0%E6%98%8E"><span class="nav-text">异常（接口）声明</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#noexcept%E5%85%B3%E9%94%AE%E5%AD%97"><span class="nav-text">noexcept关键字</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%82%E5%B8%B8%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%92%8C%E6%A0%88%E8%A7%A3%E6%97%8B"><span class="nav-text">异常对象的生命周期和栈解旋</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%82%E5%B8%B8%E4%B8%AD%E7%9A%84%E5%A4%9A%E6%80%81"><span class="nav-text">异常中的多态</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%87%E5%87%86%E5%BC%82%E5%B8%B8%E7%B1%BBstd-exception"><span class="nav-text">标准异常类std::exception</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%87%E5%87%86%E5%BC%82%E5%B8%B8%E7%B1%BB%E7%9A%84%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B"><span class="nav-text">标准异常类的使用示例</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BC%82%E5%B8%B8%E7%B1%BB%E7%BB%A7%E6%89%BF%E6%A0%87%E5%87%86%E5%BC%82%E5%B8%B8%E7%B1%BB"><span class="nav-text">自定义异常类继承标准异常类</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%A8%A1%E6%9D%BF%E5%9F%BA%E7%A1%80"><span class="nav-text">模板基础</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A8%A1%E6%9D%BF%E5%92%8C%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="nav-text">模板和泛型编程的概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF"><span class="nav-text">函数模板</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95%E8%A7%84%E5%88%99"><span class="nav-text">语法规则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%99%AE%E9%80%9A%E5%87%BD%E6%95%B0%E5%92%8C%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF%E7%9A%84%E8%B0%83%E7%94%A8%E8%A7%84%E5%88%99"><span class="nav-text">普通函数和函数模板的调用规则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%99%AE%E9%80%9A%E5%87%BD%E6%95%B0%E5%92%8C%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text">普通函数和函数模板的区别</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF"><span class="nav-text">类模板</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95%E8%A7%84%E5%88%99-1"><span class="nav-text">语法规则</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E5%92%8C%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="nav-text">类模板和函数模板的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E4%B8%AD%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E7%9A%84%E5%88%9B%E5%BB%BA%E6%97%B6%E6%9C%BA"><span class="nav-text">类模板中成员函数的创建时机</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E5%AF%B9%E8%B1%A1%E5%81%9A%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0"><span class="nav-text">类模板对象做函数参数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E4%B8%8E%E7%BB%A7%E6%89%BF"><span class="nav-text">类模板与继承</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E6%88%90%E5%91%98%E5%87%BD%E6%95%B0%E7%9A%84%E7%B1%BB%E5%A4%96%E5%AE%9E%E7%8E%B0"><span class="nav-text">类模板成员函数的类外实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E7%9A%84%E5%88%86%E6%96%87%E4%BB%B6%E7%BC%96%E5%86%99"><span class="nav-text">类模板的分文件编写</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E6%A8%A1%E6%9D%BF%E4%B8%8E%E5%8F%8B%E5%85%83"><span class="nav-text">类模板与友元</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B3%E4%BA%8Etypename%E5%92%8Cclass"><span class="nav-text">关于typename和class</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#STL%E9%83%A8%E5%88%86"><span class="nav-text">STL部分</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%AF%B4%E6%98%8E"><span class="nav-text">&#x3D;&#x3D;说明&#x3D;&#x3D;</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#string%E5%AE%B9%E5%99%A8"><span class="nav-text">string容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-1"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8B%BC%E6%8E%A5"><span class="nav-text">拼接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E6%89%BE%E3%80%81%E6%9B%BF%E6%8D%A2"><span class="nav-text">查找、替换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%AF%94%E8%BE%83"><span class="nav-text">比较</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6"><span class="nav-text">获取单个字符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%8E%B7%E5%8F%96%E5%AD%90%E4%B8%B2"><span class="nav-text">获取子串</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%95%BF%E5%BA%A6%E5%92%8C%E5%AE%B9%E9%87%8F"><span class="nav-text">长度和容量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8"><span class="nav-text">迭代器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B6%E4%BB%96"><span class="nav-text">其他</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#vector%E5%AE%B9%E5%99%A8"><span class="nav-text">vector容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-2"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC-1"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E9%87%8F%E5%92%8C%E5%A4%A7%E5%B0%8F"><span class="nav-text">容量和大小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4-1"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%98%E3%80%81%E5%8F%96"><span class="nav-text">存、取</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BA%A4%E6%8D%A2"><span class="nav-text">交换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%A2%84%E7%95%99%E7%A9%BA%E9%97%B4"><span class="nav-text">预留空间</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#deque%E5%AE%B9%E5%99%A8"><span class="nav-text">deque容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-3"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC-2"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E5%A4%A7%E5%B0%8F"><span class="nav-text">容器大小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4-2"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%98%E3%80%81%E5%8F%96-1"><span class="nav-text">存、取</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8E%92%E5%BA%8F"><span class="nav-text">排序</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#stack-%E5%AE%B9%E5%99%A8"><span class="nav-text">stack 容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-4"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC-3"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%98%E3%80%81%E5%8F%96-2"><span class="nav-text">存、取</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E5%A4%A7%E5%B0%8F-1"><span class="nav-text">容器大小</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#queue%E5%AE%B9%E5%99%A8"><span class="nav-text">queue容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-1"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-5"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC-4"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%98%E3%80%81%E5%8F%96-3"><span class="nav-text">存、取</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E5%A4%A7%E5%B0%8F-2"><span class="nav-text">容器大小</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#list%E5%AE%B9%E5%99%A8"><span class="nav-text">list容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-2"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-6"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC%E5%92%8C%E4%BA%A4%E6%8D%A2"><span class="nav-text">赋值和交换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E5%A4%A7%E5%B0%8F-3"><span class="nav-text">容器大小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4-3"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AD%98%E3%80%81%E5%8F%96-4"><span class="nav-text">存、取</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%8D%E8%BD%AC%E5%92%8C%E6%8E%92%E5%BA%8F"><span class="nav-text">反转和排序</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#pair%E5%AF%B9%E7%BB%84"><span class="nav-text">pair对组</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA"><span class="nav-text">创建</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E8%8E%B7%E5%8F%96"><span class="nav-text">数据获取</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#set%E5%AE%B9%E5%99%A8%E5%92%8Cmultiset%E5%AE%B9%E5%99%A8"><span class="nav-text">set容器和multiset容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-3"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0-7"><span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%B5%8B%E5%80%BC-5"><span class="nav-text">赋值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4-4"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%B9%E5%99%A8%E5%A4%A7%E5%B0%8F-4"><span class="nav-text">容器大小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BA%A4%E6%8D%A2-1"><span class="nav-text">交换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E6%89%BE"><span class="nav-text">查找</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%92%E5%BA%8F%E8%A7%84%E5%88%99"><span class="nav-text">自定义排序规则</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#map%E5%AE%B9%E5%99%A8%E5%92%8Cmultimap%E5%AE%B9%E5%99%A8"><span class="nav-text">map容器和multimap容器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E5%92%8C%E8%B5%8B%E5%80%BC%E5%87%BD%E6%95%B0"><span class="nav-text">构造和赋值函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%A7%E5%B0%8F%E5%92%8C%E4%BA%A4%E6%8D%A2"><span class="nav-text">大小和交换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%8F%92%E5%85%A5%E5%92%8C%E5%88%A0%E9%99%A4-5"><span class="nav-text">插入和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E6%89%BE%E5%92%8C%E5%88%A0%E9%99%A4"><span class="nav-text">查找和删除</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%92%E5%BA%8F"><span class="nav-text">自定义排序</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1"><span class="nav-text">函数对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-4"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-text">函数对象的使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B0%93%E8%AF%8D%EF%BC%88predicate%EF%BC%89%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="nav-text">谓词（predicate）的概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#STL%E7%9A%84%E5%86%85%E5%BB%BA%E5%87%BD%E6%95%B0%E5%AF%B9%E8%B1%A1"><span class="nav-text">STL的内建函数对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5-5"><span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%97%E6%95%B0%E4%BB%BF%E5%87%BD%E6%95%B0"><span class="nav-text">算数仿函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B3%E7%B3%BB%E4%BB%BF%E5%87%BD%E6%95%B0"><span class="nav-text">关系仿函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%80%BB%E8%BE%91%E4%BB%BF%E5%87%BD%E6%95%B0"><span class="nav-text">逻辑仿函数</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#STL%E5%B8%B8%E7%94%A8%E7%AE%97%E6%B3%95"><span class="nav-text">STL常用算法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0"><span class="nav-text">概述</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E9%81%8D%E5%8E%86%E7%AE%97%E6%B3%95"><span class="nav-text">常用遍历算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E6%9F%A5%E6%89%BE%E7%AE%97%E6%B3%95"><span class="nav-text">常用查找算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%BB%9F%E8%AE%A1%E7%AE%97%E6%B3%95"><span class="nav-text">常用统计算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95"><span class="nav-text">常用排序算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E6%8B%B7%E8%B4%9D%E5%92%8C%E6%9B%BF%E6%8D%A2%E7%AE%97%E6%B3%95"><span class="nav-text">常用拷贝和替换算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%AE%97%E6%9C%AF%E7%94%9F%E6%88%90%E7%AE%97%E6%B3%95"><span class="nav-text">常用算术生成算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E9%9B%86%E5%90%88%E7%AE%97%E6%B3%95"><span class="nav-text">常用集合算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B6%E4%BB%96%E5%B8%B8%E7%94%A8%E7%AE%97%E6%B3%95"><span class="nav-text">其他常用算法</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#C-%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C"><span class="nav-text">C++文件操作</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0-1"><span class="nav-text">概述</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E7%9A%84%E6%89%93%E5%BC%80%E6%96%B9%E5%BC%8F"><span class="nav-text">文件的打开方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6"><span class="nav-text">文本文件</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%86%99%E6%96%87%E4%BB%B6"><span class="nav-text">写文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%BB%E6%96%87%E4%BB%B6"><span class="nav-text">读文件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6"><span class="nav-text">二进制文件</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%86%99%E6%96%87%E4%BB%B6-1"><span class="nav-text">写文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%BB%E6%96%87%E4%BB%B6-1"><span class="nav-text">读文件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A1%A5%E5%85%85%E8%AF%B4%E6%98%8E"><span class="nav-text">补充说明</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E9%A2%84%E5%A4%84%E7%90%86%E5%99%A8"><span class="nav-text">预处理器</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#define"><span class="nav-text">#define</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%80%E5%8D%95%E7%9A%84%E6%96%87%E6%9C%AC%E6%9B%BF%E6%8D%A2"><span class="nav-text">简单的文本替换</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%8F%E5%87%BD%E6%95%B0"><span class="nav-text">宏函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%8F%E7%9A%84%E4%BC%98%E5%8A%BF%E7%BC%BA%E9%99%B7"><span class="nav-text">宏的优势缺陷</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%91%BD%E5%90%8D%E7%BA%A6%E5%AE%9A"><span class="nav-text">命名约定</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#undef"><span class="nav-text">#undef</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9D%A1%E4%BB%B6%E7%BC%96%E8%AF%91"><span class="nav-text">条件编译</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%80%89%E6%8B%A9%E6%80%A7%E7%BC%96%E8%AF%91"><span class="nav-text">选择性编译</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%AE%9A%E4%B9%89"><span class="nav-text">检查是否定义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%98%B2%E6%AD%A2%E5%A4%B4%E6%96%87%E4%BB%B6%E9%87%8D%E5%A4%8D%E5%8C%85%E5%90%AB"><span class="nav-text">防止头文件重复包含</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B5%8C%E5%A5%97%E6%8C%87%E4%BB%A4"><span class="nav-text">嵌套指令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B6%E4%BB%96%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9"><span class="nav-text">其他注意事项</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#error"><span class="nav-text">#error</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#include"><span class="nav-text">#include</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%EF%BC%88%E7%A9%BA%E6%8C%87%E4%BB%A4%EF%BC%89"><span class="nav-text">#（空指令）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#pragma"><span class="nav-text">#pragma</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%A2%84%E5%AE%9A%E4%B9%89%E7%AC%A6%E5%8F%B7"><span class="nav-text">预定义符号</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0-2"><span class="nav-text">概述</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B"><span class="nav-text">使用示例</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#line"><span class="nav-text">#line</span></a></li></ol></li></ol>

    </div>
</div>
        </div>
    
</div>



                

            </div>

            

        </div>

        <div class="main-content-footer">
            <footer class="footer mt-5 py-5 h-auto text-base text-third-text-color relative border-t-2 border-t-border-color">
    <div class="info-container py-3 text-center">
        
            <div class="customize-info my-1">死亡是涅灭,抑或是永恒?</div>
        
        <div class="text-center">
            &copy;
            
              <span>2023</span>
              -
            
            2023&nbsp;&nbsp;<i class="fa-solid fa-heart fa-beat" style="--fa-animation-duration: 0.5s; color: #f54545"></i>&nbsp;&nbsp;<a href="/">雲之残骸</a>
        </div>
        
        <div class="relative text-center lg:absolute lg:left-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-left">
            <span class="lg:block text-sm">由 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="relative top-[2px] inline-block align-baseline" version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1rem" height="1rem" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path fill="#0E83CD" d="M256.4,25.8l-200,115.5L56,371.5l199.6,114.7l200-115.5l0.4-230.2L256.4,25.8z M349,354.6l-18.4,10.7l-18.6-11V275H200v79.6l-18.4,10.7l-18.6-11v-197l18.5-10.6l18.5,10.8V237h112v-79.6l18.5-10.6l18.5,10.8V354.6z"/></svg><a target="_blank" class="text-base" href="https://hexo.io">Hexo</a> 驱动</span>
            <span class="text-sm lg:block">主题&nbsp;<a class="text-base" target="_blank" href="https://github.com/EvanNotFound/hexo-theme-redefine">Redefine v2.4.4</a></span>
        </div>
        
        
            <div>
                博客已运行 <span class="odometer" id="runtime_days" ></span> 天 <span class="odometer" id="runtime_hours"></span> 小时 <span class="odometer" id="runtime_minutes"></span> 分钟 <span class="odometer" id="runtime_seconds"></span> 秒
            </div>
        
        
            <script data-swup-reload-script>
                try {
                    function odometer_init() {
                    const elements = document.querySelectorAll('.odometer');
                    elements.forEach(el => {
                        new Odometer({
                            el,
                            format: '( ddd).dd',
                            duration: 200
                        });
                    });
                    }
                    odometer_init();
                } catch (error) {}
            </script>
        
        
        
    </div>  
</footer>
        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="article-tools-list">
        <!-- TOC aside toggle -->
        
            <li class="right-bottom-tools page-aside-toggle">
                <i class="fa-regular fa-outdent"></i>
            </li>
        

        <!-- go comment -->
        
    </ul>
</div>

        </div>
    

    <div class="right-side-tools-container">
        <div class="side-tools-container">
    <ul class="hidden-tools-list">
        <li class="right-bottom-tools tool-font-adjust-plus flex justify-center items-center">
            <i class="fa-regular fa-magnifying-glass-plus"></i>
        </li>

        <li class="right-bottom-tools tool-font-adjust-minus flex justify-center items-center">
            <i class="fa-regular fa-magnifying-glass-minus"></i>
        </li>

        <li class="right-bottom-tools tool-expand-width flex justify-center items-center">
            <i class="fa-regular fa-expand"></i>
        </li>

        <li class="right-bottom-tools tool-dark-light-toggle flex justify-center items-center">
            <i class="fa-regular fa-moon"></i>
        </li>

        <!-- rss -->
        

        

        <li class="right-bottom-tools tool-scroll-to-bottom flex justify-center items-center">
            <i class="fa-regular fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="visible-tools-list">
        <li class="right-bottom-tools toggle-tools-list flex justify-center items-center">
            <i class="fa-regular fa-cog fa-spin"></i>
        </li>
        
            <li class="right-bottom-tools tool-scroll-to-top flex justify-center items-center">
                <i class="arrow-up fas fa-arrow-up"></i>
                <span class="percent"></span>
            </li>
        
        
    </ul>
</div>

    </div>

    <div class="image-viewer-container">
    <img src="">
</div>


    
        <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
          <span class="search-input-field-pre">
            <i class="fa-solid fa-keyboard"></i>
          </span>
            <div class="search-input-container">
                <input autocomplete="off"
                       autocorrect="off"
                       autocapitalize="off"
                       placeholder="搜索..."
                       spellcheck="false"
                       type="search"
                       class="search-input"
                >
            </div>
            <span class="popup-btn-close">
                <i class="fa-solid fa-times"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fa-solid fa-spinner fa-spin-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>

    

</main>


    
<script src="/js/libs/Swup.min.js"></script>

<script src="/js/libs/SwupSlideTheme.min.js"></script>

<script src="/js/libs/SwupScriptsPlugin.min.js"></script>

<script src="/js/libs/SwupProgressPlugin.min.js"></script>

<script src="/js/libs/SwupScrollPlugin.min.js"></script>

<script>
    const swup = new Swup({
        plugins: [
            new SwupScriptsPlugin({
                optin: true,
            }),
            new SwupProgressPlugin(),
            new SwupScrollPlugin({
                offset: 80,
            }),
            new SwupSlideTheme({
                mainElement: ".main-content-body",
            }),
        ],
        containers: ["#swup"],
    });

    swup.hooks.on("page:view", () => {
        Global.refresh();
    });

    // if (document.readyState === "complete") {
    //
    // } else {
    //     document.addEventListener("DOMContentLoaded", () => init());
    // }
</script>






<script src="/js/utils.js" type="module"></script>

<script src="/js/main.js" type="module"></script>

<script src="/js/layouts/navbarShrink.js" type="module"></script>

<script src="/js/tools/scrollTopBottom.js" type="module"></script>

<script src="/js/tools/lightDarkSwitch.js" type="module"></script>

<script src="/js/layouts/categoryList.js" type="module"></script>



    
<script src="/js/tools/localSearch.js"></script>






    
<script src="/js/layouts/lazyload.js"></script>




    
<script src="/js/tools/runtime.js"></script>

    
<script src="/js/libs/odometer.min.js"></script>

    
<link rel="stylesheet" href="/assets/odometer-theme-minimal.css">




  
<script src="/js/libs/Typed.min.js"></script>

  
<script src="/js/plugins/typed.js"></script>




    
<script src="/js/libs/mermaid.min.js"></script>

    
<script src="/js/plugins/mermaid.js"></script>




    
<script src="/js/libs/minimasonry.min.js"></script>

    
<script src="/js/plugins/masonry.js" type="module"></script>




<div class="post-scripts" data-swup-reload-script>
    
        
<script src="/js/libs/anime.min.js"></script>

        
<script src="/js/tools/tocToggle.js" type="module"></script>

<script src="/js/layouts/toc.js" type="module"></script>

<script src="/js/plugins/tabs.js" type="module"></script>

    
</div>


</body>
</html>
